Collaborators: Shane Blowes, Jon Chase, Helmut Hillebrand, Michael Burrows, Amanda Bates, Uli Brose, Benoit Gauzens, Laura Antao Assistance: Katherine Lew, Josef Hauser

Introduction

Methods

library(data.table) # for handling large datasets
library(ggplot2) # for some plotting
library(nlme) # for ME models
library(beanplot) # for beanplots
library(maps) # for map
library(gridExtra) # to combine ggplots together
library(grid) # to combine ggplots together

options(width=500) # turn off most text wrapping

# tell RStudio to use project root directory as the root for this notebook. Needed since we are storing code in a separate directory.
knitr::opts_knit$set(root.dir = rprojroot::find_rstudio_root_file()) 
# Turnover and covariates assembled by turnover_vs_temperature_prep.Rmd
trends <- fread('output/turnover_w_covariates.csv.gz')

# set realm order
trends[, REALM := factor(REALM, levels = c('Freshwater', 'Marine', 'Terrestrial'), ordered = FALSE)]

# realm that combined Terrestrial and Freshwater, for interacting with human impact
trends[, REALM2 := REALM]
levels(trends$REALM2) = list(TerrFresh = "Freshwater", TerrFresh = "Terrestrial", Marine = "Marine")

# group Marine invertebrates/plants in with All
trends[, taxa_mod2 := taxa_mod]
trends[taxa_mod == 'Marine invertebrates/plants', taxa_mod2 := 'All']

Log-transform some variables, then center and scale.

trends[, tempave.sc := scale(tempave)]
trends[, tempave_metab.sc := scale(tempave_metab)]
trends[, seas.sc := scale(seas)]
trends[, microclim.sc := scale(log(microclim))]
trends[, temptrend.sc := scale(temptrend)]
trends[, temptrend_abs.sc := scale(abs(temptrend))]
trends[, npp.sc := scale(log(npp))]
trends[, mass.sc := scale(log(mass_mean_weight))]
trends[, speed.sc := scale(log(speed_mean_weight+1))]
trends[, lifespan.sc := scale(log(lifespan_mean_weight))]
trends[, thermal_bias.sc := scale(thermal_bias)]
trends[, consumerfrac.sc := scale(consfrac)]
trends[, endothermfrac.sc := scale(endofrac)]
trends[, nspp.sc := scale(log(Nspp))]
trends[, human.sc := scale(human)]

Do the variables look ok?

# histograms to examine
cexmain = 0.6
par(mfrow = c(3,5))
invisible(trends[, hist(tempave.sc, main = 'Environmental temperature (°C)', cex.main = cexmain)])
invisible(trends[, hist(tempave_metab.sc, main = 'Metabolic temperature (°C)', cex.main = cexmain)])
invisible(trends[, hist(seas.sc, main = 'Seasonality (°C)', cex.main = cexmain)])
invisible(trends[, hist(microclim.sc, main = 'log Microclimates (°C)', cex.main = cexmain)])
invisible(trends[, hist(temptrend.sc, main = 'Temperature trend (°C/yr)', cex.main = cexmain)])
invisible(trends[, hist(temptrend_abs.sc, main = 'log abs(Temperature trend) (°C/yr)', cex.main = cexmain)])
invisible(trends[, hist(mass.sc, main = 'log Mass (g)', cex.main = cexmain)])
invisible(trends[, hist(speed.sc, main = 'log Speed (km/hr)', cex.main = cexmain)])
invisible(trends[, hist(lifespan.sc, main = 'log Lifespan (yr)', cex.main = cexmain)])
invisible(trends[, hist(consumerfrac.sc, main = 'Consumers (fraction)', cex.main = cexmain)])
invisible(trends[, hist(endothermfrac.sc, main = 'Endotherms (fraction)', cex.main = cexmain)])
invisible(trends[, hist(nspp.sc, main = 'log Species richness', cex.main = cexmain)])
invisible(trends[, hist(thermal_bias.sc, main = 'Thermal bias (°C)', cex.main = cexmain)])
invisible(trends[, hist(npp.sc, main = 'log Net primary productivity', cex.main = cexmain)])
invisible(trends[, hist(human.sc, main = 'Human impact score', cex.main = cexmain)])

Check correlations among variables. Pearson’s r is on the lower diagonal.

panel.cor <- function(x, y, digits = 2, prefix = "", cex.cor, ...)
{
    usr <- par("usr"); on.exit(par(usr))
    par(usr = c(0, 1, 0, 1))
    r <- cor(x, y, use = 'pairwise.complete.obs')
    txt <- format(c(r, 0.123456789), digits = digits)[1]
    txt <- paste0(prefix, txt)
    if(missing(cex.cor)) cex.cor <- 0.8/strwidth(txt)
    text(0.5, 0.5, txt) #, cex = cex.cor * r)
}
pairs(formula = ~ REALM + tempave.sc + tempave_metab.sc + seas.sc + microclim.sc + temptrend.sc + temptrend_abs.sc +  mass.sc + speed.sc + lifespan.sc + consumerfrac.sc + endothermfrac.sc + nspp.sc + thermal_bias.sc + npp.sc + human.sc, data = trends, gap = 1/10, cex = 0.2, col = '#00000022', lower.panel = panel.cor)

Mass and lifespan look tightly correlated, but r only 0.56…? Tempave_metab and lifespan don’t look tightly correlated, but r= -0.81 Tempave_metab and speed don’t look tightly correlated, but r= -0.83 Lifespan and speed don’t look tightly correlated, but r = 0.73

Examine how many data points are available

Just turnover

cat('Overall # time-series: ', nrow(trends), '\n')
Overall # time-series:  53013 
cat('# studies: ', trends[, length(unique(STUDY_ID))], '\n')
# studies:  332 
cat('Data points: ', trends[, sum(nyrBT)], '\n')
Data points:  293973 
trends[, table(REALM)]
REALM
 Freshwater      Marine Terrestrial 
       1025       48647        3341 
trends[, table(taxa_mod)]
taxa_mod
                        All                  Amphibians                     Benthos                       Birds 
                       1705                         379                        4679                       13741 
                       Fish               Invertebrates                     Mammals Marine invertebrates/plants 
                      28473                        2996                         525                         206 
                      Plant                    Reptiles 
                        305                           4 
trends[, table(taxa_mod, REALM)]
                             REALM
taxa_mod                      Freshwater Marine Terrestrial
  All                                  0   1702           3
  Amphibians                           2      0         377
  Benthos                              0   4679           0
  Birds                                0  11099        2642
  Fish                              1006  27467           0
  Invertebrates                       15   2901          80
  Mammals                              0    478          47
  Marine invertebrates/plants          0    206           0
  Plant                                1    115         189
  Reptiles                             1      0           3

With all covariates

# the cases we can compare
apply(trends[, .(Jtutrend, REALM, tempave.sc, tempave_metab.sc, seas.sc, microclim.sc, temptrend.sc, mass.sc, speed.sc, lifespan.sc, consumerfrac.sc, endothermfrac.sc, nspp.sc, thermal_bias.sc, npp.sc, human.sc)], MARGIN = 2, FUN = function(x) sum(!is.na(x)))
        Jtutrend            REALM       tempave.sc tempave_metab.sc          seas.sc     microclim.sc 
           53013            53013            49916            49916            49916            51834 
    temptrend.sc          mass.sc         speed.sc      lifespan.sc  consumerfrac.sc endothermfrac.sc 
           49916            52820            52689            51540            47534            53013 
         nspp.sc  thermal_bias.sc           npp.sc         human.sc 
           53013            49371            52863            53013 
i <- trends[, complete.cases(Jtutrend, temptrend.sc, tempave_metab.sc, REALM, seas.sc, microclim.sc, npp.sc, mass.sc, speed.sc, lifespan.sc, consumerfrac.sc, thermal_bias.sc)]
cat('Overall # time-series: ', sum(i), '\n')
Overall # time-series:  43585 
cat('# studies: ', trends[i, length(unique(STUDY_ID))], '\n')
# studies:  250 
cat('Data points: ', trends[i, sum(nyrBT)], '\n')
Data points:  222824 
trends[i, table(REALM)]
REALM
 Freshwater      Marine Terrestrial 
       1008       39735        2842 
trends[i, table(taxa_mod)]
taxa_mod
          All    Amphibians       Benthos         Birds          Fish Invertebrates       Mammals         Plant 
          521            12           590         11803         27372          2567           518           200 
     Reptiles 
            2 
trends[i, table(taxa_mod, REALM)]
               REALM
taxa_mod        Freshwater Marine Terrestrial
  All                    0    520           1
  Amphibians             2      0          10
  Benthos                0    590           0
  Birds                  0   9221        2582
  Fish                 993  26379           0
  Invertebrates         12   2484          71
  Mammals                0    477          41
  Plant                  1     64         135
  Reptiles               0      0           2

Choose the variance structure for mixed effects modles

Try combinations of

  • variance scaled to a power of the number of years in the community time-series
  • variance scaled to a power of the abs temperature trend
  • random intercept for taxa_mod
  • random intercept for STUDY_ID
  • random slope (abs temperature trend) for taxa_mod
  • random slope (abs temperature trend) for STUDY_ID
  • random intercept for rarefyID (for overdispersion)

And choose the one with lowest AIC (not run: takes a long time)

# fit models for variance structure
fixed <- formula(Jtutrend ~ REALM + tempave_metab.sc + seas.sc + microclim.sc + npp.sc + temptrend_abs.sc +
                     mass.sc + speed.sc + lifespan.sc + consumerfrac.sc + thermal_bias.sc)
i <- trends[, complete.cases(Jtutrend, REALM, tempave_metab.sc, seas.sc, microclim.sc, npp.sc, temptrend_abs.sc,
                             mass.sc, speed.sc, lifespan.sc, consumerfrac.sc, thermal_bias.sc)]
mods <- vector('list', 0)
mods[[1]] <- gls(fixed, data = trends[i,])
mods[[2]] <- gls(fixed, data = trends[i,], weights = varPower(-0.5, ~nyrBT))
mods[[3]] <- gls(fixed, data = trends[i,], weights = varPower(0.5, ~ abs(temptrend)))

mods[[4]] <- lme(fixed, data = trends[i,], random = ~1|taxa_mod2, control = lmeControl(opt = "optim"))
mods[[5]] <- lme(fixed, data = trends[i,], random = ~1|STUDY_ID, control = lmeControl(opt = "optim"))
mods[[6]] <- lme(fixed, data = trends[i,], random = ~1|taxa_mod2/STUDY_ID, control = lmeControl(opt = "optim"))
mods[[7]] <- lme(fixed, data = trends[i,], random = ~1|STUDY_ID/rarefyID, control = lmeControl(opt = "optim"))
mods[[8]] <- lme(fixed, data = trends[i,], random = ~1|taxa_mod2/STUDY_ID/rarefyID, control = lmeControl(opt = "optim"))

mods[[9]] <- lme(fixed, data = trends[i,], random = ~temptrend_abs.sc | taxa_mod)
mods[[10]] <- lme(fixed, data = trends[i,], random = ~temptrend_abs.sc | STUDY_ID)
mods[[11]] <- lme(fixed, data = trends[i,], random = ~temptrend_abs.sc | taxa_mod2/STUDY_ID, control = lmeControl(opt = "optim"))
mods[[12]] <- lme(fixed, data = trends[i,], random = list(STUDY_ID = ~ temptrend_abs.sc, rarefyID = ~1)) # includes overdispersion. new formula so that random slope is only for study level (not enough data to extend to rarefyID).
mods[[13]] <- lme(fixed, data = trends[i,], random = list(taxa_mod2 = ~ temptrend_abs.sc, STUDY_ID = ~ temptrend_abs.sc, rarefyID = ~1)) # 30+ min to fit

mods[[14]] <- lme(fixed, data = trends[i,], random = ~1|STUDY_ID, weights = varPower(-0.5, ~nyrBT))
mods[[15]] <- lme(fixed, data = trends[i,], random = ~1|taxa_mod2, weights = varPower(-0.5, ~nyrBT))
mods[[16]] <- lme(fixed, data = trends[i,], random = ~1|taxa_mod2/STUDY_ID, weights = varPower(-0.5, ~nyrBT))
mods[[17]] <- lme(fixed, data = trends[i,], random = ~1|STUDY_ID/rarefyID, weights = varPower(-0.5, ~nyrBT))
mods[[18]] <- lme(fixed, data = trends[i,], random = ~1|taxa_mod2/STUDY_ID/rarefyID, weights = varPower(-0.5, ~nyrBT))
mods[[19]] <- lme(fixed, data = trends[i,], random = ~temptrend_abs.sc|STUDY_ID, weights = varPower(-0.5, ~nyrBT))
mods[[20]] <- lme(fixed, data = trends[i,], random = list(STUDY_ID = ~ temptrend_abs.sc, rarefyID = ~1), weights = varPower(-0.5, ~nyrBT))
mods[[21]] <- lme(fixed, data = trends[i,], random = list(taxa_mod2 = ~ temptrend_abs.sc, STUDY_ID = ~ 1), weights = varPower(-0.5, ~nyrBT))
mods[[22]] <- lme(fixed, data = trends[i,], random = list(taxa_mod2 = ~ temptrend_abs.sc, STUDY_ID = ~ 1, rarefyID = ~1), weights = varPower(-0.5, ~nyrBT))
mods[[23]] <- lme(fixed, data = trends[i,], random = list(taxa_mod2 = ~ temptrend_abs.sc, STUDY_ID = ~ temptrend_abs.sc), weights = varPower(-0.5, ~nyrBT)) # singular precision warning with lmeControl(opt = 'optim') and convergence error without
mods[[24]] <- lme(fixed, data = trends[i,], random = list(taxa_mod2 = ~ temptrend_abs.sc, STUDY_ID = ~ temptrend_abs.sc, rarefyID = ~1), weights = varPower(-0.5, ~nyrBT)) # singular precision warning with lmeControl(opt = 'optim') and convergence error without

mods[[25]] <- lme(fixed, data = trends[i,], random = ~1|taxa_mod2, weights = varPower(-0.5, ~abs(temptrend)))
mods[[26]] <- lme(fixed, data = trends[i,], random = ~1|STUDY_ID, weights = varPower(-0.5, ~abs(temptrend)))
mods[[27]] <- lme(fixed, data = trends[i,], random = ~1|STUDY_ID/rarefyID, weights = varPower(-0.5, ~abs(temptrend)))
mods[[28]] <- lme(fixed, data = trends[i,], random = ~1|taxa_mod2/STUDY_ID/rarefyID, weights = varPower(-0.5, ~abs(temptrend)))
mods[[29]] <- lme(fixed, data = trends[i,], random = ~temptrend_abs.sc|STUDY_ID, weights = varPower(-0.5, ~abs(temptrend)))
mods[[30]] <- lme(fixed, data = trends[i,], random = ~temptrend_abs.sc|taxa_mod2/STUDY_ID, weights = varPower(-0.5, ~abs(temptrend)), control = lmeControl(opt = "optim"))
mods[[31]] <- lme(fixed, data = trends[i,], random = list(STUDY_ID = ~ temptrend_abs.sc, rarefyID = ~1), weights = varPower(-0.5, ~abs(temptrend)))
mods[[32]] <- lme(fixed, data = trends[i,], random = list(taxa_mod2 = ~ temptrend_abs.sc, STUDY_ID = ~ temptrend_abs.sc, rarefyID = ~1), weights = varPower(-0.5, ~abs(temptrend)), control = lmeControl(opt = "optim")) # singular precision warning

aics <- sapply(mods, AIC)
minaics <- aics - min(aics)
minaics
which.min(aics)

Chooses the random slopes (temptrend_abs) & intercepts for STUDY_ID, overdispersion, and variance scaled to number of years. We haven’t dealt with potential testing on the boundary issues here yet.

Results

Where do we have data?

world <- map_data('world')
ggplot(world, aes(x = long, y = lat, group = group)) +
    geom_polygon(fill = 'lightgray', color = 'white') +
    geom_point(data = trends, aes(rarefyID_x, rarefyID_y, group = REALM, color = REALM), size = 0.5, alpha = 0.4)  +
    scale_color_brewer(palette="Set1", name = 'Realm') +
  theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(),
        panel.background = element_blank(), axis.line = element_line(colour = "black"),
        legend.key=element_blank(),
        axis.text=element_text(size=16),
        axis.title=element_text(size=20)) +
  labs(x = 'Longitude (°)', y = 'Latitude (°)')

Mostly northern hemisphere, but spread all over. No so much in Africa or much of Asia.

Plot turnover vs. explanatory variables

Lines are ggplot smoother fits by realm.

Strong trends with temperature change, but trends are pretty symmetric around no trend in temperature, which implies warming or cooling drives similar degree of community turnover. Some indication of less turnover for larger organisms (mass) Higher turnover on land with higher seasonality? More turnover for shorter-lived organisms? No really clear differences among realms.

Average rates of turnover

trends[abs(temptrend) >= 0.5, .(mean(Jtutrend), sd(Jtutrend)/sqrt(.N))] # turnover per year for locations changing temperature
trends[abs(temptrend) < 0.1, .(mean(Jtutrend), sd(Jtutrend)/sqrt(.N))] # not changing temperature
trends[temptrend >= 0.5, .(mean(Jtutrend), sd(Jtutrend)/sqrt(.N))] # warming
trends[temptrend <= -0.5, .(mean(Jtutrend), sd(Jtutrend)/sqrt(.N))] # cooling

trends[abs(temptrend) >= 0.5 & abs(rarefyID_y) < 35, .(mean(Jtutrend), sd(Jtutrend)/sqrt(.N))] # tropics and sub-tropics
trends[abs(temptrend) >= 0.5 & abs(rarefyID_y) >= 35 & abs(rarefyID_y) < 66.56339, .(mean(Jtutrend), sd(Jtutrend)/sqrt(.N))] # temperate
trends[abs(temptrend) >= 0.5 & abs(rarefyID_y) >= 66.56339, .(mean(Jtutrend), sd(Jtutrend)/sqrt(.N))] # arctic

Compare covariates across realms

i <- trends[, !duplicated(rarefyID)]; sum(i)
[1] 53013
par(mfrow=c(5,3))
beanplot(rarefyID_y ~ REALM, data = trends[i,], what = c(1,1,1,1), col = c("#CAB2D6", "#33A02C", "#B2DF8A"), border = "#CAB2D6", ylab = 'Latitude (degN)', ll = 0.05)
beanplot(tempave ~ REALM, data = trends[i,], what = c(1,1,1,1), col = c("#CAB2D6", "#33A02C", "#B2DF8A"), border = "#CAB2D6", ylab = 'Temperature (degC)', ll = 0.05)
beanplot(tempave_metab ~ REALM, data = trends[i,], what = c(1,1,1,1), col = c("#CAB2D6", "#33A02C", "#B2DF8A"), border = "#CAB2D6", ylab = 'Metabolic Temperature (degC)', ll = 0.05, bw = 'nrd0') # nrd0 bandwidth to calculation gap
beanplot(seas ~ REALM, data = trends[i,], what = c(1,1,1,1), col = c("#CAB2D6", "#33A02C", "#B2DF8A"), border = "#CAB2D6", ylab = 'Seasonality (degC)', ll = 0.05)
beanplot(microclim ~ REALM, data = trends[i,], what = c(1,1,1,1), col = c("#CAB2D6", "#33A02C", "#B2DF8A"), border = "#CAB2D6", ylab = 'Microclimates (degC)', ll = 0.05)
log="y" selected
beanplot(temptrend ~ REALM, data = trends[i,], what = c(1,1,1,1), col = c("#CAB2D6", "#33A02C", "#B2DF8A"), border = "#CAB2D6", ylab = 'Temperature trend (degC/yr)', ll = 0.05)
beanplot(mass_mean_weight ~ REALM, data = trends[i,], what = c(1,1,1,1), col = c("#CAB2D6", "#33A02C", "#B2DF8A"), border = "#CAB2D6", ylab = 'Mass (g)', ll = 0.05, log = 'y')
beanplot(speed_mean_weight +1 ~ REALM, data = trends[i,], what = c(1,1,1,1), col = c("#CAB2D6", "#33A02C", "#B2DF8A"), border = "#CAB2D6", ylab = 'Speed (km/hr)', ll = 0.05, log = 'y')
beanplot(lifespan_mean_weight ~ REALM, data = trends[i,], what = c(1,1,1,1), col = c("#CAB2D6", "#33A02C", "#B2DF8A"), border = "#CAB2D6", ylab = 'Lifespan (yr)', ll = 0.05, log = 'y')
#beanplot(consfrac ~ REALM, data = trends[i,], what = c(1,1,1,1), col = c("#CAB2D6", "#33A02C", "#B2DF8A"), border = "#CAB2D6", ylab = 'Consumers (fraction)', ll = 0.05, log = '') # too sparse
#beanplot(endofrac ~ REALM, data = trends[i,], what = c(1,1,1,1), col = c("#CAB2D6", "#33A02C", "#B2DF8A"), border = "#CAB2D6", ylab = 'Endotherms (fraction)', ll = 0.05, log = '') # too sparse
beanplot(Nspp ~ REALM, data = trends[i,], what = c(1,1,1,1), col = c("#CAB2D6", "#33A02C", "#B2DF8A"), border = "#CAB2D6", ylab = 'Number of species', ll = 0.05, log = 'y')
beanplot(thermal_bias ~ REALM, data = trends[i & !is.na(thermal_bias),], what = c(1,1,1,1), col = c("#CAB2D6", "#33A02C", "#B2DF8A"), border = "#CAB2D6", ylab = 'Thermal bias (degC)', ll = 0.05)
beanplot(npp ~ REALM, data = trends[i,], what = c(1,1,1,1), col = c("#CAB2D6", "#33A02C", "#B2DF8A"), border = "#CAB2D6", ylab = 'NPP', ll = 0.05)
log="y" selected
beanplot(human ~ REALM, data = trends[i,], what = c(1,1,1,1), col = c("#CAB2D6", "#33A02C", "#B2DF8A"), border = "#CAB2D6", ylab = 'Human impact score', ll = 0.05)

Marine are in generally warmer locations (seawater doesn’t freeze) Marine have much lower seasonality. Marine and freshwater have some very small masses (plankton), but much of dataset is similar to terrestrial. Marine has a lot of slow, crawling organisms, but land has plants. Land also has birds (fast).

Temperature-only model (Jtutrend, Jbetatrend, Horntrend)

i <- trends[, complete.cases(Jtutrend, REALM, temptrend)]

randef <- list(STUDY_ID = ~ abs(temptrend), rarefyID = ~1)
varef <- varPower(-0.5, ~nyrBT)

if(file.exists('temp/modonlyTtrend.rds')){
  modonlyTtrend <- readRDS('temp/modonlyTtrend.rds')
} else {
  modonlyTtrend <- lme(Jtutrend ~ abs(temptrend)*REALM,
                   random = randef, weights = varef, data = trends[i,], method = 'REML')
  saveRDS(modonlyTtrend, file = 'temp/modonlyTtrend.rds')
}

i2 <- trends[, complete.cases(Jbetatrend, REALM, temptrend)]
if(file.exists('temp/modonlyTtrendJbeta.rds')){
  modonlyTtrendJbeta <- readRDS('temp/modonlyTtrendJbeta.rds')
} else {
  modonlyTtrendJbeta <- lme(Jbetatrend ~ abs(temptrend)*REALM,
                   random = randef, weights = varef, data = trends[i2,], method = 'REML', 
                   control=lmeControl(msMaxIter = 100, maxIter = 100))
  saveRDS(modonlyTtrendJbeta, file = 'temp/modonlyTtrendJbeta.rds')
}

i3 <- trends[, complete.cases(Horntrend, REALM, temptrend)]
if(file.exists('temp/modonlyTtrendHorn.rds')){
  modonlyTtrendHorn <- readRDS('temp/modonlyTtrendHorn.rds')
} else {
  modonlyTtrendHorn <- lme(Horntrend ~ abs(temptrend)*REALM,
                   random = randef, weights = varef, data = trends[i3,], method = 'REML')
  saveRDS(modonlyTtrendHorn, file = 'temp/modonlyTtrendHorn.rds')
}

summary(modonlyTtrend)
Linear mixed-effects model fit by REML
 Data: trends[i, ] 

Random effects:
 Formula: ~abs(temptrend) | STUDY_ID
 Structure: General positive-definite, Log-Cholesky parametrization
               StdDev     Corr  
(Intercept)    0.04375688 (Intr)
abs(temptrend) 0.29351811 -0.123

 Formula: ~1 | rarefyID %in% STUDY_ID
        (Intercept)  Residual
StdDev: 0.001792571 0.2893301

Variance function:
 Structure: Power of variance covariate
 Formula: ~nyrBT 
 Parameter estimates:
    power 
-1.223838 
Fixed effects: Jtutrend ~ abs(temptrend) * REALM 
 Correlation: 
                                (Intr) abs(t) REALMM REALMT a():REALMM
abs(temptrend)                  -0.424                                
REALMMarine                     -0.934  0.396                         
REALMTerrestrial                -0.923  0.391  0.862                  
abs(temptrend):REALMMarine       0.407 -0.960 -0.407 -0.375           
abs(temptrend):REALMTerrestrial  0.387 -0.913 -0.362 -0.433  0.876    

Standardized Within-Group Residuals:
        Min          Q1         Med          Q3         Max 
-8.38476416 -0.29781039  0.08738927  0.54929160  6.52538535 

Number of Observations: 49916
Number of Groups: 
              STUDY_ID rarefyID %in% STUDY_ID 
                   317                  49916 
summary(modonlyTtrendJbeta)
Linear mixed-effects model fit by REML
 Data: trends[i2, ] 

Random effects:
 Formula: ~abs(temptrend) | STUDY_ID
 Structure: General positive-definite, Log-Cholesky parametrization
               StdDev     Corr  
(Intercept)    0.05691594 (Intr)
abs(temptrend) 0.34739161 -0.16 

 Formula: ~1 | rarefyID %in% STUDY_ID
        (Intercept)  Residual
StdDev: 1.28009e-06 0.3525846

Variance function:
 Structure: Power of variance covariate
 Formula: ~nyrBT 
 Parameter estimates:
    power 
-1.394679 
Fixed effects: Jbetatrend ~ abs(temptrend) * REALM 
 Correlation: 
                                (Intr) abs(t) REALMM REALMT a():REALMM
abs(temptrend)                  -0.428                                
REALMMarine                     -0.933  0.399                         
REALMTerrestrial                -0.926  0.396  0.864                  
abs(temptrend):REALMMarine       0.411 -0.961 -0.411 -0.380           
abs(temptrend):REALMTerrestrial  0.390 -0.913 -0.364 -0.437  0.877    

Standardized Within-Group Residuals:
       Min         Q1        Med         Q3        Max 
-7.3578768 -0.1587203  0.2033006  0.6705745  6.5270460 

Number of Observations: 49916
Number of Groups: 
              STUDY_ID rarefyID %in% STUDY_ID 
                   317                  49916 
summary(modonlyTtrendHorn)
Linear mixed-effects model fit by REML
 Data: trends[i3, ] 

Random effects:
 Formula: ~abs(temptrend) | STUDY_ID
 Structure: General positive-definite, Log-Cholesky parametrization
               StdDev    Corr  
(Intercept)    0.0549979 (Intr)
abs(temptrend) 0.3228314 -0.095

 Formula: ~1 | rarefyID %in% STUDY_ID
        (Intercept)  Residual
StdDev: 0.007989212 0.3034899

Variance function:
 Structure: Power of variance covariate
 Formula: ~nyrBT 
 Parameter estimates:
    power 
-1.217439 
Fixed effects: Horntrend ~ abs(temptrend) * REALM 
 Correlation: 
                                (Intr) abs(t) REALMM REALMT a():REALMM
abs(temptrend)                  -0.399                                
REALMMarine                     -0.921  0.368                         
REALMTerrestrial                -0.919  0.367  0.847                  
abs(temptrend):REALMMarine       0.381 -0.954 -0.378 -0.350           
abs(temptrend):REALMTerrestrial  0.363 -0.908 -0.334 -0.408  0.867    

Standardized Within-Group Residuals:
        Min          Q1         Med          Q3         Max 
-6.21250285 -0.32193926  0.06521414  0.53688251  6.03752738 

Number of Observations: 48800
Number of Groups: 
              STUDY_ID rarefyID %in% STUDY_ID 
                   276                  48800 

Plot the temp-only coefficients

# make table of coefficients
coefs <- as.data.frame(summary(modonlyTtrend)$tTable)
coefs2 <- as.data.frame(summary(modonlyTtrendJbeta)$tTable)
coefs3 <- as.data.frame(summary(modonlyTtrendHorn)$tTable)
coefs$mod <- 'Jtu'
coefs2$mod <- 'Jbeta'
coefs3$mod <- 'Horn'
rows1 <- which(grepl('temptrend', rownames(coefs))) # extract temperature effect
cols <- c('Value', 'Std.Error', 'mod')
allcoefs <- rbind(coefs[rows1, cols], coefs2[rows1, cols], coefs3[rows1, cols])
allcoefs$Value[grepl('REALMMarine', rownames(allcoefs))] <- 
  allcoefs$Value[grepl('REALMMarine', rownames(allcoefs))] + 
  allcoefs$Value[!grepl('REALM', rownames(allcoefs))] # add intercept to marine effects
allcoefs$Value[grepl('REALMTerrestrial', rownames(allcoefs))] <- 
  allcoefs$Value[grepl('REALMTerrestrial', rownames(allcoefs))] + 
  allcoefs$Value[!grepl('REALM', rownames(allcoefs))] # add intercept to terrestrial effects

allcoefs$lCI <- allcoefs$Value - allcoefs$Std.Error # lower confidence interval
allcoefs$uCI <- allcoefs$Value + allcoefs$Std.Error
allcoefs$y <- c(3, 2, 1, 2.9, 1.9, 0.9, 2.8, 1.8, 0.8) # y-values
allcoefs$col <- c(rep('black', 3), rep('light grey', 3), rep('dark grey', 3))
allcoefs$realm <- rep(c('Freshwater', 'Marine', 'Terrestrial'), 3)

par(las = 1, mai = c(0.8, 2, 0.1, 0.1))
plot(0,0, col = 'white', xlim=c(-0.02, 0.85), ylim = c(0.7,3), 
     yaxt='n', xlab = 'Turnover per |°C/yr|', ylab ='')
axis(2, at = 3:1, labels = c('Freshwater', 'Marine', 'Terrestrial'), cex.axis = 0.7)
abline(v = 0, col = 'grey')
for(i in 1:nrow(allcoefs)){
  with(allcoefs[i, ], points(Value, y, pch = 16, col = col))
  with(allcoefs[i, ], lines(x = c(lCI, uCI), y = c(y, y), col = col))
}
legend('bottomright', col = c('black', 'dark grey', 'light grey'), lwd = 1, pch = 16, 
       legend = c('Jaccard turnover', 'Jaccard total', 'Horn-Morisita'))

Nicer plots of turnover vs. temperature data and model fit

Scatterplot, violin plots, and coefficient plots all together

# on macbook: fig.width=3, fig.height=2.375, fig.retina=3, out.width=3, out.height=2.375
# on external monitor: 
trends[temptrend <= -0.5, temptrendtext := 'Cooling']
trends[abs(temptrend) <= 0.1, temptrendtext := 'Stable']
trends[temptrend >= 0.5, temptrendtext := 'Warming']

trends[abs(rarefyID_y) < 35, latzone := 'Subtropics']
trends[abs(rarefyID_y) >= 35 & abs(rarefyID_x) < 66.56339, latzone := 'Temperate'] 
trends[abs(rarefyID_y) >= 66.56339, latzone := 'Polar']
trends[, latzone := factor(latzone, levels = c('Subtropics', 'Temperate', 'Polar'))]

p1 <- ggplot(trends, aes(temptrend, Jtutrend, color = REALM, fill = REALM, size = nyrBT)) +
  geom_point(na.rm = TRUE, shape = 16, alpha = 0.1) + 
  geom_smooth(data=subset(trends, abs(temptrend) < 0.75), method = 'gam', formula = y ~ s(x, bs = "cs"), 
              na.rm = TRUE) +
  scale_color_brewer(palette="Set1", name = 'Realm') + 
  scale_fill_brewer(palette="Set1", name = 'Realm') + 
  labs(x = 'Temperature trend (°C/yr)', y = 'Jaccard turnover', tag = 'A') +
  scale_size_continuous(range = c(1, 8), breaks = c(2, 5, 20)) +
  guides(size = guide_legend(title = 'Years',
                             override.aes = list(linetype=0, fill = NA, alpha = 1))) +
  theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(),
        panel.background = element_blank(), axis.line = element_line(colour = "black"),
        legend.key=element_blank(),
        legend.key.size = unit(0.5,"line"), 
        axis.text=element_text(size=8),
        axis.title=element_text(size=10))

p2 <- ggplot(trends[!is.na(temptrendtext), ], aes(temptrendtext, Jtutrend)) +
  geom_violin(draw_quantiles = c(0.25, 0.5, 0.75), fill = 'grey') +
  labs(x = '', y = 'Jaccard turnover', tag = 'B') +
  theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(),
        panel.background = element_blank(), axis.line = element_line(colour = "black"),
        legend.key=element_blank(),
        axis.text=element_text(size=8),
        axis.title=element_text(size=10))

p3 <- ggplot(trends[abs(temptrend) >= 0.5 & !is.na(latzone), ], aes(latzone, Jtutrend)) +
  geom_violin(draw_quantiles = c(0.25, 0.5, 0.75), fill = 'grey') + 
  labs(x = '', y = '', tag = 'C') +
  theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(),
        panel.background = element_blank(), axis.line = element_line(colour = "black"),
        legend.key=element_blank(),
        axis.text=element_text(size=7),
        axis.title=element_text(size=10))

p4 <- ggplot(allcoefs, aes(Value, y, group = mod, color = mod)) +
  geom_errorbarh(aes(xmin = lCI, xmax = uCI, height = 0)) + 
  geom_point() + 
  labs(x = expression(atop('Temperature change effect', '(Turnover '~degree*'C'^'-1'*')')), y = '', tag = 'D') +
  scale_color_grey() + 
  theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(),
        panel.background = element_blank(), axis.line = element_line(colour = "black"),
        legend.position='none',
        axis.text=element_text(size=7),
        axis.title=element_text(size=7)) + 
  coord_cartesian(xlim =c(0, 1)) +
  scale_y_continuous(name = '', breaks = c(1, 2, 3), labels = c('Terrestrial', 'Marine', 'Freshwater'))

grid.arrange(p1, p2, p3, p4, ncol = 3, layout_matrix = rbind(c(1,1,1), c(2,3,4)),
             heights=c(unit(0.66, "npc"), unit(0.34, "npc")))

Full models

Try static covariates plus interactions of abs temperature trend with each covariate:

  • realm
  • environmental temperature
  • average metabolic temperature
  • seasonality
  • microclimates
  • NPP
  • speed
  • mass
  • lifespan
  • consumer vs. producer
  • thermal bias

Except for thermal bias: interact with temperature trend (not abs)

Full model for Jaccard total

summary(modTfull1)
Linear mixed-effects model fit by REML
 Data: trends[i, ] 

Random effects:
 Formula: ~temptrend_abs.sc | STUDY_ID
 Structure: General positive-definite, Log-Cholesky parametrization
                 StdDev     Corr  
(Intercept)      0.04834247 (Intr)
temptrend_abs.sc 0.03064449 0.335 

 Formula: ~1 | rarefyID %in% STUDY_ID
         (Intercept)  Residual
StdDev: 0.0008908894 0.2861661

Variance function:
 Structure: Power of variance covariate
 Formula: ~nyrBT 
 Parameter estimates:
    power 
-1.235108 
Fixed effects: Jtutrend ~ temptrend_abs.sc * REALM + temptrend_abs.sc * tempave.sc +      temptrend_abs.sc * tempave_metab.sc + temptrend_abs.sc *      seas.sc + temptrend_abs.sc * microclim.sc + temptrend_abs.sc *      mass.sc + temptrend_abs.sc * speed.sc + temptrend_abs.sc *      lifespan.sc + temptrend_abs.sc * consumerfrac.sc + temptrend_abs.sc *      endothermfrac.sc + temptrend_abs.sc * nspp.sc + temptrend.sc *      thermal_bias.sc + temptrend_abs.sc * npp.sc + temptrend_abs.sc *      human.sc:REALM2 
 Correlation: 
                                          (Intr) tmpt_. REALMM REALMT tmpv.s tmpv_. ses.sc mcrcl. mss.sc spd.sc lfspn. cnsmr. endth. nspp.s tmptr.
temptrend_abs.sc                           0.344                                                                                                  
REALMMarine                               -0.917 -0.314                                                                                           
REALMTerrestrial                          -0.878 -0.314  0.802                                                                                    
tempave.sc                                 0.002 -0.008 -0.015  0.002                                                                             
tempave_metab.sc                           0.047  0.030 -0.035 -0.050 -0.338                                                                      
seas.sc                                   -0.036 -0.019  0.051 -0.020  0.181  0.007                                                               
microclim.sc                              -0.012 -0.019  0.015 -0.016 -0.044  0.133  0.135                                                        
mass.sc                                    0.012 -0.012  0.000  0.003 -0.042 -0.515 -0.052 -0.027                                                 
speed.sc                                   0.019  0.002 -0.032 -0.032 -0.011  0.121 -0.059 -0.015 -0.090                                          
lifespan.sc                                0.046  0.047 -0.028 -0.048 -0.023  0.713  0.075  0.031 -0.813  0.190                                   
consumerfrac.sc                           -0.072 -0.057  0.081  0.342 -0.001 -0.109  0.002  0.004  0.060 -0.164 -0.131                            
endothermfrac.sc                           0.172  0.080 -0.091 -0.347  0.134 -0.234  0.004 -0.044  0.011  0.085 -0.024 -0.415                     
nspp.sc                                   -0.013  0.021 -0.010 -0.023 -0.013  0.032 -0.033 -0.024 -0.169 -0.062  0.138  0.012  0.053              
temptrend.sc                              -0.008 -0.015  0.008  0.008 -0.087  0.004 -0.034  0.018  0.017 -0.004 -0.014  0.005 -0.007 -0.019       
thermal_bias.sc                            0.029 -0.011 -0.045 -0.008  0.671 -0.024 -0.113 -0.112  0.033  0.028 -0.059 -0.002 -0.012 -0.069  0.000
npp.sc                                    -0.007 -0.033 -0.001  0.008 -0.221  0.176 -0.229 -0.291  0.004 -0.012  0.044 -0.043 -0.070 -0.119  0.022
temptrend_abs.sc:REALMMarine              -0.327 -0.952  0.337  0.296  0.006 -0.021  0.031  0.020  0.014 -0.006 -0.032  0.060 -0.055 -0.026  0.013
temptrend_abs.sc:REALMTerrestrial         -0.297 -0.852  0.269  0.369  0.014 -0.048 -0.051 -0.025  0.015 -0.010 -0.040  0.151 -0.156 -0.041  0.010
temptrend_abs.sc:tempave.sc                0.001 -0.008 -0.004  0.013  0.489 -0.305  0.006 -0.082 -0.083 -0.040  0.014  0.026  0.151  0.021 -0.085
temptrend_abs.sc:tempave_metab.sc          0.014  0.050 -0.008 -0.024 -0.183  0.668  0.078  0.126 -0.299  0.033  0.434 -0.077 -0.191  0.030  0.013
temptrend_abs.sc:seas.sc                  -0.013 -0.038  0.018 -0.027  0.109  0.079  0.648  0.080 -0.045 -0.018  0.036  0.006 -0.034 -0.015 -0.005
temptrend_abs.sc:microclim.sc             -0.012 -0.030  0.009 -0.012 -0.042  0.131  0.086  0.768 -0.033  0.010  0.013 -0.001 -0.056  0.013  0.029
temptrend_abs.sc:mass.sc                  -0.006 -0.014  0.008  0.009 -0.085 -0.330 -0.051 -0.028  0.605  0.007 -0.528  0.031  0.001 -0.105  0.020
temptrend_abs.sc:speed.sc                  0.001  0.010 -0.003 -0.010 -0.025  0.015 -0.007  0.007  0.018  0.286  0.005 -0.057  0.039 -0.040 -0.010
temptrend_abs.sc:lifespan.sc               0.026  0.071 -0.013 -0.023  0.026  0.465  0.045  0.014 -0.515  0.021  0.645 -0.076 -0.034  0.112 -0.010
temptrend_abs.sc:consumerfrac.sc          -0.054 -0.094  0.054  0.135  0.032 -0.122 -0.011 -0.002  0.039 -0.061 -0.111  0.360 -0.118 -0.002  0.003
temptrend_abs.sc:endothermfrac.sc          0.072  0.164 -0.046 -0.145  0.140 -0.270 -0.050 -0.077 -0.002  0.023 -0.035 -0.135  0.443  0.054 -0.018
temptrend_abs.sc:nspp.sc                   0.012  0.036 -0.019 -0.027 -0.005  0.066 -0.030  0.010 -0.110 -0.029  0.125 -0.001  0.021  0.583 -0.029
temptrend.sc:thermal_bias.sc               0.006  0.006 -0.007 -0.004  0.076  0.038  0.031 -0.054 -0.010  0.013  0.006 -0.004 -0.013 -0.023 -0.354
                                          thrm_. npp.sc t_.:REALMM t_.:REALMT tmptrnd_bs.sc:t. t_.:_. tmptrnd_bs.sc:ss. tmptrnd_bs.sc:mc.
temptrend_abs.sc                                                                                                                         
REALMMarine                                                                                                                              
REALMTerrestrial                                                                                                                         
tempave.sc                                                                                                                               
tempave_metab.sc                                                                                                                         
seas.sc                                                                                                                                  
microclim.sc                                                                                                                             
mass.sc                                                                                                                                  
speed.sc                                                                                                                                 
lifespan.sc                                                                                                                              
consumerfrac.sc                                                                                                                          
endothermfrac.sc                                                                                                                         
nspp.sc                                                                                                                                  
temptrend.sc                                                                                                                             
thermal_bias.sc                                                                                                                          
npp.sc                                    -0.085                                                                                         
temptrend_abs.sc:REALMMarine               0.009  0.019                                                                                  
temptrend_abs.sc:REALMTerrestrial          0.003  0.023  0.801                                                                           
temptrend_abs.sc:tempave.sc                0.049 -0.066  0.006      0.027                                                                
temptrend_abs.sc:tempave_metab.sc          0.056  0.072 -0.038     -0.067     -0.502                                                     
temptrend_abs.sc:seas.sc                   0.079 -0.136  0.054     -0.064      0.137            0.073                                    
temptrend_abs.sc:microclim.sc             -0.003 -0.256  0.034     -0.026     -0.060            0.106  0.113                             
temptrend_abs.sc:mass.sc                  -0.011  0.019  0.020      0.023     -0.117           -0.479 -0.047            -0.018           
temptrend_abs.sc:speed.sc                  0.002  0.004 -0.026     -0.031     -0.043            0.063 -0.016            -0.003           
temptrend_abs.sc:lifespan.sc               0.004  0.020 -0.052     -0.064      0.028            0.667  0.042             0.010           
temptrend_abs.sc:consumerfrac.sc          -0.003 -0.034  0.103      0.309      0.046           -0.164 -0.026             0.000           
temptrend_abs.sc:endothermfrac.sc         -0.035 -0.033 -0.111     -0.365      0.369           -0.413 -0.048            -0.065           
temptrend_abs.sc:nspp.sc                  -0.032 -0.037 -0.051     -0.071      0.034            0.040 -0.050            -0.022           
temptrend.sc:thermal_bias.sc              -0.023 -0.008 -0.007     -0.004      0.044            0.046  0.047            -0.040           
                                          tmptrnd_bs.sc:ms. tmptrnd_bs.sc:sp. tmptrnd_bs.sc:l. tmptrnd_bs.sc:c. tmptrnd_bs.sc:nd. tmptrnd_bs.sc:ns.
temptrend_abs.sc                                                                                                                                   
REALMMarine                                                                                                                                        
REALMTerrestrial                                                                                                                                   
tempave.sc                                                                                                                                         
tempave_metab.sc                                                                                                                                   
seas.sc                                                                                                                                            
microclim.sc                                                                                                                                       
mass.sc                                                                                                                                            
speed.sc                                                                                                                                           
lifespan.sc                                                                                                                                        
consumerfrac.sc                                                                                                                                    
endothermfrac.sc                                                                                                                                   
nspp.sc                                                                                                                                            
temptrend.sc                                                                                                                                       
thermal_bias.sc                                                                                                                                    
npp.sc                                                                                                                                             
temptrend_abs.sc:REALMMarine                                                                                                                       
temptrend_abs.sc:REALMTerrestrial                                                                                                                  
temptrend_abs.sc:tempave.sc                                                                                                                        
temptrend_abs.sc:tempave_metab.sc                                                                                                                  
temptrend_abs.sc:seas.sc                                                                                                                           
temptrend_abs.sc:microclim.sc                                                                                                                      
temptrend_abs.sc:mass.sc                                                                                                                           
temptrend_abs.sc:speed.sc                 -0.026                                                                                                   
temptrend_abs.sc:lifespan.sc              -0.831             0.093                                                                                 
temptrend_abs.sc:consumerfrac.sc           0.061            -0.188            -0.175                                                               
temptrend_abs.sc:endothermfrac.sc         -0.018             0.126            -0.032           -0.292                                              
temptrend_abs.sc:nspp.sc                  -0.208            -0.083             0.201            0.001            0.103                             
temptrend.sc:thermal_bias.sc              -0.016             0.028             0.002           -0.003           -0.031            -0.029           
                                          tm.:_. tmptrnd_bs.sc:np. h.:REALM2T h.:REALM2M t_.:.:REALM2T
temptrend_abs.sc                                                                                      
REALMMarine                                                                                           
REALMTerrestrial                                                                                      
tempave.sc                                                                                            
tempave_metab.sc                                                                                      
seas.sc                                                                                               
microclim.sc                                                                                          
mass.sc                                                                                               
speed.sc                                                                                              
lifespan.sc                                                                                           
consumerfrac.sc                                                                                       
endothermfrac.sc                                                                                      
nspp.sc                                                                                               
temptrend.sc                                                                                          
thermal_bias.sc                                                                                       
npp.sc                                                                                                
temptrend_abs.sc:REALMMarine                                                                          
temptrend_abs.sc:REALMTerrestrial                                                                     
temptrend_abs.sc:tempave.sc                                                                           
temptrend_abs.sc:tempave_metab.sc                                                                     
temptrend_abs.sc:seas.sc                                                                              
temptrend_abs.sc:microclim.sc                                                                         
temptrend_abs.sc:mass.sc                                                                              
temptrend_abs.sc:speed.sc                                                                             
temptrend_abs.sc:lifespan.sc                                                                          
temptrend_abs.sc:consumerfrac.sc                                                                      
temptrend_abs.sc:endothermfrac.sc                                                                     
temptrend_abs.sc:nspp.sc                                                                              
temptrend.sc:thermal_bias.sc                                                                          
 [ reached getOption("max.print") -- omitted 5 rows ]

Standardized Within-Group Residuals:
        Min          Q1         Med          Q3         Max 
-8.34115139 -0.34664125  0.05370777  0.53577626  6.61354550 

Number of Observations: 43585
Number of Groups: 
              STUDY_ID rarefyID %in% STUDY_ID 
                   250                  43585 

Plot the coefficients from the full model


coefs <- summary(modTfull1)$tTable
par(las = 1, mai = c(0.5, 3, 0.1, 0.1))
rows1 <- which(!grepl('Intercept', rownames(coefs)))
plot(0,0, col = 'white', xlim=c(-0.05, 0.08), ylim = c(1,length(rows1)), yaxt='n', xlab = '', ylab ='')
axis(2, at = length(rows1):1, labels = rownames(coefs)[rows1], cex.axis = 0.7)
abline(v = 0, col = 'grey')
for(i in 1:length(rows1)){
  x = coefs[rows1[i], 1]
  se = coefs[rows1[i], 2]
  points(x, length(rows1) + 1 - i, pch = 16)
  lines(x = c(x-se, x+se), y = c(length(rows1) + 1 - i, length(rows1) + 1 - i))
}

Plot interactions

Plot residuals against each predictor

resids <- resid(modTfull1)
preds <- getData(modTfull1)
col = '#00000033'
cex = 0.5
par(mfrow = c(4,4))
boxplot(resids ~ preds$REALM, cex = cex, col = col)
plot(preds$temptrend_abs.sc, resids, cex = cex, col = col)
plot(preds$temptrend.sc, resids, cex = cex, col = col)
plot(preds$tempave.sc, resids, cex = cex, col = col)
plot(preds$tempave_metab.sc, resids, cex = cex, col = col)
plot(preds$seas.sc, resids, cex = cex, col = col)
plot(preds$microclim.sc, resids, cex = cex, col = col)
plot(preds$mass.sc, resids, cex = cex, col = col)
plot(preds$speed.sc, resids, cex = cex, col = col)
plot(preds$lifespan.sc, resids, cex = cex, col = col)
plot(preds$consumerfrac.sc, resids, cex = cex, col = col)
plot(preds$endothermfrac.sc, resids, cex = cex, col = col)
plot(preds$nspp.sc, resids, cex = cex, col = col)
plot(preds$thermal_bias.sc, resids, cex = cex, col = col)
plot(preds$npp.sc, resids, cex = cex, col = col)
plot(preds$human.sc, resids, cex = cex, col = col)

Sensitivity analysis: total turnover and Horn-Morisita models

Fit full models for total and HM

i2 <- trends[, complete.cases(Jbetatrend, REALM, tempave.sc, tempave_metab.sc, seas.sc, microclim.sc, 
                             temptrend.sc, temptrend_abs.sc, mass.sc, speed.sc, lifespan.sc, 
                             consumerfrac.sc, endothermfrac.sc, nspp.sc, thermal_bias.sc, npp.sc, human.sc)]
i3 <- trends[, complete.cases(Horntrend, REALM, tempave.sc, tempave_metab.sc, seas.sc, microclim.sc, 
                             temptrend.sc, temptrend_abs.sc, mass.sc, speed.sc, lifespan.sc, 
                             consumerfrac.sc, endothermfrac.sc, nspp.sc, thermal_bias.sc, npp.sc, human.sc)]

randef <- list(STUDY_ID = ~ temptrend_abs.sc, rarefyID = ~1)
varef <- varPower(-0.5, ~nyrBT)

# full models
if(file.exists('temp/modTfullJbeta.rds')){
  modTfullJbeta <- readRDS('temp/modTfullJbeta.rds')
} else {
  modTfullJbeta <- lme(Jbetatrend ~ temptrend_abs.sc*REALM + 
                     temptrend_abs.sc*tempave.sc +
                     temptrend_abs.sc*tempave_metab.sc + 
                     temptrend_abs.sc*seas.sc + 
                     temptrend_abs.sc*microclim.sc + 
                     temptrend_abs.sc*mass.sc + 
                     temptrend_abs.sc*speed.sc + 
                     temptrend_abs.sc*lifespan.sc + 
                     temptrend_abs.sc*consumerfrac.sc +
                     temptrend_abs.sc*endothermfrac.sc +
                     temptrend_abs.sc*nspp.sc +
                     temptrend.sc*thermal_bias.sc +
                     temptrend_abs.sc*npp.sc +
                     temptrend_abs.sc*human.sc*REALM,
                   random = randef, weights = varef, data = trends[i2,], method = 'REML')
  saveRDS(modTfullJbeta, file = 'temp/modTfullJbeta.rds')
}

if(file.exists('temp/modTfullHorn.rds')){
  modTfullHorn <- readRDS('temp/modTfullHorn.rds')
} else {
  modTfullHorn <- lme(Horntrend ~ temptrend_abs.sc*REALM + 
                     temptrend_abs.sc*tempave.sc +
                     temptrend_abs.sc*tempave_metab.sc + 
                     temptrend_abs.sc*seas.sc + 
                     temptrend_abs.sc*microclim.sc + 
                     temptrend_abs.sc*mass.sc + 
                     temptrend_abs.sc*speed.sc + 
                     temptrend_abs.sc*lifespan.sc + 
                     temptrend_abs.sc*consumerfrac.sc +
                     temptrend_abs.sc*endothermfrac.sc +
                     temptrend_abs.sc*nspp.sc +
                     temptrend.sc*thermal_bias.sc +
                     temptrend_abs.sc*npp.sc +
                     temptrend_abs.sc*human.sc*REALM,
                   random = randef, weights = varef, data = trends[i3,], method = 'REML')
  saveRDS(modTfullHorn, file = 'temp/modTfullHorn.rds')
}

summary(modTfullJbeta)
Linear mixed-effects model fit by REML
 Data: trends[i2, ] 

Random effects:
 Formula: ~temptrend_abs.sc | STUDY_ID
 Structure: General positive-definite, Log-Cholesky parametrization
                 StdDev     Corr  
(Intercept)      0.06301414 (Intr)
temptrend_abs.sc 0.03804902 0.262 

 Formula: ~1 | rarefyID %in% STUDY_ID
         (Intercept)  Residual
StdDev: 0.0009169992 0.3174155

Variance function:
 Structure: Power of variance covariate
 Formula: ~nyrBT 
 Parameter estimates:
    power 
-1.350808 
Fixed effects: Jbetatrend ~ temptrend_abs.sc * REALM + temptrend_abs.sc * tempave.sc +      temptrend_abs.sc * tempave_metab.sc + temptrend_abs.sc *      seas.sc + temptrend_abs.sc * microclim.sc + temptrend_abs.sc *      mass.sc + temptrend_abs.sc * speed.sc + temptrend_abs.sc *      lifespan.sc + temptrend_abs.sc * consumerfrac.sc + temptrend_abs.sc *      endothermfrac.sc + temptrend_abs.sc * nspp.sc + temptrend.sc *      thermal_bias.sc + temptrend_abs.sc * npp.sc + temptrend_abs.sc *      human.sc * REALM 
 Correlation: 
                                           (Intr) tmpt_. REALMMr REALMTr tmpv.s tmpv_. ses.sc mcrcl. mss.sc
temptrend_abs.sc                            0.276                                                          
REALMMarine                                -0.918 -0.251                                                   
REALMTerrestrial                           -0.885 -0.259  0.812                                            
tempave.sc                                 -0.005 -0.008 -0.007   0.000                                    
tempave_metab.sc                            0.037  0.028 -0.027  -0.038  -0.316                            
seas.sc                                    -0.025 -0.021  0.036  -0.014   0.206  0.011                     
microclim.sc                               -0.008 -0.017  0.010  -0.011  -0.026  0.142  0.149              
mass.sc                                     0.011 -0.008 -0.001   0.001  -0.046 -0.516 -0.055 -0.033       
speed.sc                                    0.014  0.003 -0.023  -0.022  -0.011  0.122 -0.060 -0.015 -0.087
lifespan.sc                                 0.032  0.042 -0.020  -0.035  -0.020  0.720  0.075  0.034 -0.806
consumerfrac.sc                            -0.055 -0.055  0.069   0.323  -0.027 -0.080  0.008  0.009  0.050
endothermfrac.sc                            0.155  0.082 -0.082  -0.316   0.099 -0.190  0.008 -0.036  0.022
nspp.sc                                    -0.009  0.017 -0.009  -0.019  -0.016  0.027 -0.029 -0.022 -0.162
temptrend.sc                               -0.006 -0.012  0.006   0.007  -0.099  0.004 -0.031  0.014  0.018
thermal_bias.sc                             0.017 -0.010 -0.028  -0.007   0.655 -0.003 -0.093 -0.093  0.030
npp.sc                                     -0.003 -0.027 -0.004  -0.001  -0.216  0.173 -0.237 -0.290  0.009
human.sc                                   -0.115  0.048  0.108   0.101   0.005 -0.006 -0.005  0.003  0.011
temptrend_abs.sc:REALMMarine               -0.262 -0.954  0.269   0.244   0.007 -0.021  0.032  0.018  0.011
temptrend_abs.sc:REALMTerrestrial          -0.244 -0.859  0.220   0.312   0.011 -0.041 -0.037 -0.019  0.012
temptrend_abs.sc:tempave.sc                -0.002 -0.008 -0.001   0.009   0.549 -0.328  0.054 -0.066 -0.084
temptrend_abs.sc:tempave_metab.sc           0.013  0.042 -0.008  -0.019  -0.204  0.724  0.065  0.127 -0.325
temptrend_abs.sc:seas.sc                   -0.009 -0.037  0.015  -0.016   0.154  0.065  0.715  0.092 -0.049
temptrend_abs.sc:microclim.sc              -0.008 -0.025  0.006  -0.009  -0.028  0.135  0.097  0.810 -0.039
temptrend_abs.sc:mass.sc                   -0.004 -0.008  0.006   0.007  -0.087 -0.361 -0.056 -0.032  0.661
temptrend_abs.sc:speed.sc                   0.001  0.008 -0.003  -0.009  -0.025  0.017 -0.014  0.003  0.013
temptrend_abs.sc:lifespan.sc                0.020  0.059 -0.010  -0.018   0.023  0.513  0.048  0.018 -0.553
temptrend_abs.sc:consumerfrac.sc           -0.048 -0.084  0.047   0.124   0.032 -0.109 -0.011 -0.001  0.033
                                           spd.sc lfspn. cnsmr. endth. nspp.s tmptr. thrm_. npp.sc hmn.sc
temptrend_abs.sc                                                                                         
REALMMarine                                                                                              
REALMTerrestrial                                                                                         
tempave.sc                                                                                               
tempave_metab.sc                                                                                         
seas.sc                                                                                                  
microclim.sc                                                                                             
mass.sc                                                                                                  
speed.sc                                                                                                 
lifespan.sc                                 0.194                                                        
consumerfrac.sc                            -0.123 -0.109                                                 
endothermfrac.sc                            0.065 -0.027 -0.410                                          
nspp.sc                                    -0.062  0.130  0.003  0.040                                   
temptrend.sc                               -0.004 -0.013  0.006 -0.005 -0.020                            
thermal_bias.sc                             0.028 -0.055 -0.011 -0.015 -0.075  0.001                     
npp.sc                                     -0.017  0.044 -0.051 -0.062 -0.120  0.024 -0.077              
human.sc                                    0.005  0.005  0.002  0.002 -0.009  0.006  0.008 -0.020       
temptrend_abs.sc:REALMMarine               -0.008 -0.030  0.058 -0.056 -0.023  0.010  0.009  0.015 -0.045
temptrend_abs.sc:REALMTerrestrial          -0.009 -0.035  0.145 -0.166 -0.035  0.008  0.003  0.019 -0.037
temptrend_abs.sc:tempave.sc                -0.041  0.012  0.016  0.132  0.020 -0.097  0.036 -0.083 -0.008
temptrend_abs.sc:tempave_metab.sc           0.042  0.477 -0.060 -0.174  0.024  0.012  0.070  0.086  0.001
temptrend_abs.sc:seas.sc                   -0.024  0.038  0.021 -0.017 -0.015 -0.004  0.087 -0.157 -0.015
temptrend_abs.sc:microclim.sc               0.007  0.017  0.003 -0.047  0.012  0.025  0.002 -0.263 -0.005
temptrend_abs.sc:mass.sc                   -0.003 -0.569  0.028  0.003 -0.113  0.022 -0.009  0.017  0.014
temptrend_abs.sc:speed.sc                   0.363  0.014 -0.053  0.039 -0.047 -0.008  0.004  0.003  0.009
temptrend_abs.sc:lifespan.sc                0.038  0.703 -0.063 -0.040  0.114 -0.010  0.002  0.024  0.004
temptrend_abs.sc:consumerfrac.sc           -0.065 -0.100  0.324 -0.130  0.002  0.002  0.001 -0.026 -0.006
                                           tm_.:REALMM tm_.:REALMT tmptrnd_bs.sc:t. t_.:_.
temptrend_abs.sc                                                                          
REALMMarine                                                                               
REALMTerrestrial                                                                          
tempave.sc                                                                                
tempave_metab.sc                                                                          
seas.sc                                                                                   
microclim.sc                                                                              
mass.sc                                                                                   
speed.sc                                                                                  
lifespan.sc                                                                               
consumerfrac.sc                                                                           
endothermfrac.sc                                                                          
nspp.sc                                                                                   
temptrend.sc                                                                              
thermal_bias.sc                                                                           
npp.sc                                                                                    
human.sc                                                                                  
temptrend_abs.sc:REALMMarine                                                              
temptrend_abs.sc:REALMTerrestrial           0.811                                         
temptrend_abs.sc:tempave.sc                 0.006       0.020                             
temptrend_abs.sc:tempave_metab.sc          -0.032      -0.054      -0.498                 
temptrend_abs.sc:seas.sc                    0.050      -0.043       0.169            0.056
temptrend_abs.sc:microclim.sc               0.027      -0.020      -0.043            0.103
temptrend_abs.sc:mass.sc                    0.014       0.015      -0.113           -0.475
temptrend_abs.sc:speed.sc                  -0.022      -0.023      -0.041            0.056
temptrend_abs.sc:lifespan.sc               -0.043      -0.053       0.022            0.673
temptrend_abs.sc:consumerfrac.sc            0.096       0.300       0.035           -0.137
                                           tmptrnd_bs.sc:ss. tmptrnd_bs.sc:mc. tmptrnd_bs.sc:ms.
temptrend_abs.sc                                                                                
REALMMarine                                                                                     
REALMTerrestrial                                                                                
tempave.sc                                                                                      
tempave_metab.sc                                                                                
seas.sc                                                                                         
microclim.sc                                                                                    
mass.sc                                                                                         
speed.sc                                                                                        
lifespan.sc                                                                                     
consumerfrac.sc                                                                                 
endothermfrac.sc                                                                                
nspp.sc                                                                                         
temptrend.sc                                                                                    
thermal_bias.sc                                                                                 
npp.sc                                                                                          
human.sc                                                                                        
temptrend_abs.sc:REALMMarine                                                                    
temptrend_abs.sc:REALMTerrestrial                                                               
temptrend_abs.sc:tempave.sc                                                                     
temptrend_abs.sc:tempave_metab.sc                                                               
temptrend_abs.sc:seas.sc                                                                        
temptrend_abs.sc:microclim.sc               0.119                                               
temptrend_abs.sc:mass.sc                   -0.050            -0.022                             
temptrend_abs.sc:speed.sc                  -0.021            -0.006            -0.023           
temptrend_abs.sc:lifespan.sc                0.040             0.013            -0.819           
temptrend_abs.sc:consumerfrac.sc           -0.024             0.002             0.048           
                                           tmptrnd_bs.sc:sp. tmptrnd_bs.sc:l. tmptrnd_bs.sc:c.
temptrend_abs.sc                                                                              
REALMMarine                                                                                   
REALMTerrestrial                                                                              
tempave.sc                                                                                    
tempave_metab.sc                                                                              
seas.sc                                                                                       
microclim.sc                                                                                  
mass.sc                                                                                       
speed.sc                                                                                      
lifespan.sc                                                                                   
consumerfrac.sc                                                                               
endothermfrac.sc                                                                              
nspp.sc                                                                                       
temptrend.sc                                                                                  
thermal_bias.sc                                                                               
npp.sc                                                                                        
human.sc                                                                                      
temptrend_abs.sc:REALMMarine                                                                  
temptrend_abs.sc:REALMTerrestrial                                                             
temptrend_abs.sc:tempave.sc                                                                   
temptrend_abs.sc:tempave_metab.sc                                                             
temptrend_abs.sc:seas.sc                                                                      
temptrend_abs.sc:microclim.sc                                                                 
temptrend_abs.sc:mass.sc                                                                      
temptrend_abs.sc:speed.sc                                                                     
temptrend_abs.sc:lifespan.sc                0.088                                             
temptrend_abs.sc:consumerfrac.sc           -0.156            -0.148                           
                                           tmptrnd_bs.sc:nd. tmptrnd_bs.sc:ns. tm.:_. tmptrnd_bs.sc:np.
temptrend_abs.sc                                                                                       
REALMMarine                                                                                            
REALMTerrestrial                                                                                       
tempave.sc                                                                                             
tempave_metab.sc                                                                                       
seas.sc                                                                                                
microclim.sc                                                                                           
mass.sc                                                                                                
speed.sc                                                                                               
lifespan.sc                                                                                            
consumerfrac.sc                                                                                        
endothermfrac.sc                                                                                       
nspp.sc                                                                                                
temptrend.sc                                                                                           
thermal_bias.sc                                                                                        
npp.sc                                                                                                 
human.sc                                                                                               
temptrend_abs.sc:REALMMarine                                                                           
temptrend_abs.sc:REALMTerrestrial                                                                      
temptrend_abs.sc:tempave.sc                                                                            
temptrend_abs.sc:tempave_metab.sc                                                                      
temptrend_abs.sc:seas.sc                                                                               
temptrend_abs.sc:microclim.sc                                                                          
temptrend_abs.sc:mass.sc                                                                               
temptrend_abs.sc:speed.sc                                                                              
temptrend_abs.sc:lifespan.sc                                                                           
temptrend_abs.sc:consumerfrac.sc                                                                       
                                           tmptrnd_bs.sc:h. REALMM: REALMT: t_.:REALMM:
temptrend_abs.sc                                                                       
REALMMarine                                                                            
REALMTerrestrial                                                                       
tempave.sc                                                                             
tempave_metab.sc                                                                       
seas.sc                                                                                
microclim.sc                                                                           
mass.sc                                                                                
speed.sc                                                                               
lifespan.sc                                                                            
consumerfrac.sc                                                                        
endothermfrac.sc                                                                       
nspp.sc                                                                                
temptrend.sc                                                                           
thermal_bias.sc                                                                        
npp.sc                                                                                 
human.sc                                                                               
temptrend_abs.sc:REALMMarine                                                           
temptrend_abs.sc:REALMTerrestrial                                                      
temptrend_abs.sc:tempave.sc                                                            
temptrend_abs.sc:tempave_metab.sc                                                      
temptrend_abs.sc:seas.sc                                                               
temptrend_abs.sc:microclim.sc                                                          
temptrend_abs.sc:mass.sc                                                               
temptrend_abs.sc:speed.sc                                                              
temptrend_abs.sc:lifespan.sc                                                           
temptrend_abs.sc:consumerfrac.sc                                                       
 [ reached getOption("max.print") -- omitted 9 rows ]

Standardized Within-Group Residuals:
       Min         Q1        Med         Q3        Max 
-7.6064598 -0.2375081  0.1357510  0.6185365  6.5687599 

Number of Observations: 43585
Number of Groups: 
              STUDY_ID rarefyID %in% STUDY_ID 
                   250                  43585 
summary(modTfullHorn)
Linear mixed-effects model fit by REML
 Data: trends[i3, ] 

Random effects:
 Formula: ~temptrend_abs.sc | STUDY_ID
 Structure: General positive-definite, Log-Cholesky parametrization
                 StdDev     Corr  
(Intercept)      0.06191799 (Intr)
temptrend_abs.sc 0.03262754 0.297 

 Formula: ~1 | rarefyID %in% STUDY_ID
        (Intercept)  Residual
StdDev: 0.004381157 0.2964481

Variance function:
 Structure: Power of variance covariate
 Formula: ~nyrBT 
 Parameter estimates:
    power 
-1.222775 
Fixed effects: Horntrend ~ temptrend_abs.sc * REALM + temptrend_abs.sc * tempave.sc +      temptrend_abs.sc * tempave_metab.sc + temptrend_abs.sc *      seas.sc + temptrend_abs.sc * microclim.sc + temptrend_abs.sc *      mass.sc + temptrend_abs.sc * speed.sc + temptrend_abs.sc *      lifespan.sc + temptrend_abs.sc * consumerfrac.sc + temptrend_abs.sc *      endothermfrac.sc + temptrend_abs.sc * nspp.sc + temptrend.sc *      thermal_bias.sc + temptrend_abs.sc * npp.sc + temptrend_abs.sc *      human.sc * REALM 
 Correlation: 
                                           (Intr) tmpt_. REALMMr REALMTr tmpv.s tmpv_. ses.sc mcrcl. mss.sc
temptrend_abs.sc                            0.285                                                          
REALMMarine                                -0.906 -0.256                                                   
REALMTerrestrial                           -0.874 -0.264  0.785                                            
tempave.sc                                 -0.003 -0.008 -0.008   0.006                                    
tempave_metab.sc                            0.047  0.029 -0.033  -0.053  -0.374                            
seas.sc                                    -0.039 -0.020  0.051  -0.010   0.162 -0.001                     
microclim.sc                               -0.010 -0.016  0.012  -0.014  -0.058  0.126  0.119              
mass.sc                                     0.011 -0.011  0.000   0.005  -0.043 -0.498 -0.048 -0.019       
speed.sc                                    0.016  0.001 -0.030  -0.027  -0.019  0.120 -0.070 -0.022 -0.093
lifespan.sc                                 0.041  0.046 -0.024  -0.044  -0.025  0.698  0.072  0.024 -0.808
consumerfrac.sc                            -0.060 -0.056  0.056   0.336   0.000 -0.086 -0.006  0.003  0.051
endothermfrac.sc                            0.166  0.078 -0.084  -0.340   0.140 -0.213  0.001 -0.038  0.009
nspp.sc                                    -0.012  0.021 -0.008  -0.018  -0.008  0.027 -0.029 -0.021 -0.173
temptrend.sc                               -0.007 -0.014  0.006   0.009  -0.082  0.003 -0.038  0.018  0.019
thermal_bias.sc                             0.026 -0.012 -0.038  -0.010   0.662 -0.032 -0.130 -0.131  0.032
npp.sc                                      0.000 -0.030 -0.005  -0.003  -0.225  0.183 -0.236 -0.305  0.000
human.sc                                   -0.130  0.059  0.121   0.114   0.008 -0.005 -0.004  0.008  0.012
temptrend_abs.sc:REALMMarine               -0.270 -0.949  0.279   0.248   0.005 -0.019  0.028  0.017  0.012
temptrend_abs.sc:REALMTerrestrial          -0.249 -0.849  0.221   0.315   0.016 -0.055 -0.041 -0.024  0.017
temptrend_abs.sc:tempave.sc                 0.004 -0.006 -0.007   0.012   0.417 -0.273 -0.035 -0.092 -0.081
temptrend_abs.sc:tempave_metab.sc           0.012  0.050 -0.005  -0.025  -0.152  0.623  0.082  0.127 -0.281
temptrend_abs.sc:seas.sc                   -0.008 -0.040  0.009  -0.023   0.060  0.093  0.561  0.067 -0.039
temptrend_abs.sc:microclim.sc              -0.008 -0.029  0.005  -0.013  -0.054  0.128  0.071  0.700 -0.025
temptrend_abs.sc:mass.sc                   -0.007 -0.013  0.007   0.010  -0.085 -0.305 -0.045 -0.024  0.577
temptrend_abs.sc:speed.sc                  -0.001  0.011  0.001  -0.007  -0.023  0.007  0.000  0.010  0.025
temptrend_abs.sc:lifespan.sc                0.022  0.073 -0.009  -0.020   0.028  0.434  0.040  0.008 -0.487
temptrend_abs.sc:consumerfrac.sc           -0.047 -0.092  0.052   0.102   0.031 -0.112 -0.015 -0.006  0.035
                                           spd.sc lfspn. cnsmr. endth. nspp.s tmptr. thrm_. npp.sc hmn.sc
temptrend_abs.sc                                                                                         
REALMMarine                                                                                              
REALMTerrestrial                                                                                         
tempave.sc                                                                                               
tempave_metab.sc                                                                                         
seas.sc                                                                                                  
microclim.sc                                                                                             
mass.sc                                                                                                  
speed.sc                                                                                                 
lifespan.sc                                 0.190                                                        
consumerfrac.sc                            -0.132 -0.112                                                 
endothermfrac.sc                            0.070 -0.020 -0.401                                          
nspp.sc                                    -0.059  0.137  0.008  0.048                                   
temptrend.sc                               -0.002 -0.015  0.007 -0.007 -0.016                            
thermal_bias.sc                             0.028 -0.061  0.007  0.000 -0.066  0.000                     
npp.sc                                     -0.003  0.044 -0.030 -0.059 -0.120  0.015 -0.085              
human.sc                                    0.004  0.007  0.005  0.001 -0.011  0.006  0.008 -0.024       
temptrend_abs.sc:REALMMarine               -0.004 -0.031  0.059 -0.056 -0.023  0.012  0.010  0.020 -0.056
temptrend_abs.sc:REALMTerrestrial          -0.007 -0.039  0.129 -0.153 -0.036  0.011  0.002  0.015 -0.044
temptrend_abs.sc:tempave.sc                -0.034  0.012  0.024  0.125  0.018 -0.079  0.059 -0.048 -0.009
temptrend_abs.sc:tempave_metab.sc           0.025  0.410 -0.064 -0.163  0.031  0.010  0.055  0.062  0.006
temptrend_abs.sc:seas.sc                   -0.010  0.029  0.003 -0.043 -0.018 -0.003  0.070 -0.112 -0.021
temptrend_abs.sc:microclim.sc               0.015  0.005 -0.005 -0.052  0.013  0.031  0.001 -0.236 -0.007
temptrend_abs.sc:mass.sc                    0.013 -0.499  0.024 -0.002 -0.095  0.022 -0.017  0.019  0.013
temptrend_abs.sc:speed.sc                   0.202 -0.007 -0.039  0.029 -0.038 -0.012 -0.001  0.002  0.011
temptrend_abs.sc:lifespan.sc                0.008  0.614 -0.064 -0.032  0.104 -0.010  0.008  0.017  0.007
temptrend_abs.sc:consumerfrac.sc           -0.039 -0.105  0.300 -0.094 -0.006  0.005  0.002 -0.011 -0.010
                                           tm_.:REALMM tm_.:REALMT tmptrnd_bs.sc:t. t_.:_.
temptrend_abs.sc                                                                          
REALMMarine                                                                               
REALMTerrestrial                                                                          
tempave.sc                                                                                
tempave_metab.sc                                                                          
seas.sc                                                                                   
microclim.sc                                                                              
mass.sc                                                                                   
speed.sc                                                                                  
lifespan.sc                                                                               
consumerfrac.sc                                                                           
endothermfrac.sc                                                                          
nspp.sc                                                                                   
temptrend.sc                                                                              
thermal_bias.sc                                                                           
npp.sc                                                                                    
human.sc                                                                                  
temptrend_abs.sc:REALMMarine                                                              
temptrend_abs.sc:REALMTerrestrial           0.795                                         
temptrend_abs.sc:tempave.sc                 0.004       0.029                             
temptrend_abs.sc:tempave_metab.sc          -0.036      -0.076      -0.507                 
temptrend_abs.sc:seas.sc                    0.053      -0.061       0.119            0.080
temptrend_abs.sc:microclim.sc               0.033      -0.027      -0.065            0.103
temptrend_abs.sc:mass.sc                    0.018       0.028      -0.118           -0.474
temptrend_abs.sc:speed.sc                  -0.028      -0.029      -0.043            0.060
temptrend_abs.sc:lifespan.sc               -0.053      -0.067       0.027            0.663
temptrend_abs.sc:consumerfrac.sc            0.100       0.284       0.041           -0.158
                                           tmptrnd_bs.sc:ss. tmptrnd_bs.sc:mc. tmptrnd_bs.sc:ms.
temptrend_abs.sc                                                                                
REALMMarine                                                                                     
REALMTerrestrial                                                                                
tempave.sc                                                                                      
tempave_metab.sc                                                                                
seas.sc                                                                                         
microclim.sc                                                                                    
mass.sc                                                                                         
speed.sc                                                                                        
lifespan.sc                                                                                     
consumerfrac.sc                                                                                 
endothermfrac.sc                                                                                
nspp.sc                                                                                         
temptrend.sc                                                                                    
thermal_bias.sc                                                                                 
npp.sc                                                                                          
human.sc                                                                                        
temptrend_abs.sc:REALMMarine                                                                    
temptrend_abs.sc:REALMTerrestrial                                                               
temptrend_abs.sc:tempave.sc                                                                     
temptrend_abs.sc:tempave_metab.sc                                                               
temptrend_abs.sc:seas.sc                                                                        
temptrend_abs.sc:microclim.sc               0.116                                               
temptrend_abs.sc:mass.sc                   -0.044            -0.016                             
temptrend_abs.sc:speed.sc                  -0.017            -0.006            -0.027           
temptrend_abs.sc:lifespan.sc                0.038             0.007            -0.827           
temptrend_abs.sc:consumerfrac.sc           -0.032            -0.003             0.058           
                                           tmptrnd_bs.sc:sp. tmptrnd_bs.sc:l. tmptrnd_bs.sc:c.
temptrend_abs.sc                                                                              
REALMMarine                                                                                   
REALMTerrestrial                                                                              
tempave.sc                                                                                    
tempave_metab.sc                                                                              
seas.sc                                                                                       
microclim.sc                                                                                  
mass.sc                                                                                       
speed.sc                                                                                      
lifespan.sc                                                                                   
consumerfrac.sc                                                                               
endothermfrac.sc                                                                              
nspp.sc                                                                                       
temptrend.sc                                                                                  
thermal_bias.sc                                                                               
npp.sc                                                                                        
human.sc                                                                                      
temptrend_abs.sc:REALMMarine                                                                  
temptrend_abs.sc:REALMTerrestrial                                                             
temptrend_abs.sc:tempave.sc                                                                   
temptrend_abs.sc:tempave_metab.sc                                                             
temptrend_abs.sc:seas.sc                                                                      
temptrend_abs.sc:microclim.sc                                                                 
temptrend_abs.sc:mass.sc                                                                      
temptrend_abs.sc:speed.sc                                                                     
temptrend_abs.sc:lifespan.sc                0.094                                             
temptrend_abs.sc:consumerfrac.sc           -0.164            -0.173                           
                                           tmptrnd_bs.sc:nd. tmptrnd_bs.sc:ns. tm.:_. tmptrnd_bs.sc:np.
temptrend_abs.sc                                                                                       
REALMMarine                                                                                            
REALMTerrestrial                                                                                       
tempave.sc                                                                                             
tempave_metab.sc                                                                                       
seas.sc                                                                                                
microclim.sc                                                                                           
mass.sc                                                                                                
speed.sc                                                                                               
lifespan.sc                                                                                            
consumerfrac.sc                                                                                        
endothermfrac.sc                                                                                       
nspp.sc                                                                                                
temptrend.sc                                                                                           
thermal_bias.sc                                                                                        
npp.sc                                                                                                 
human.sc                                                                                               
temptrend_abs.sc:REALMMarine                                                                           
temptrend_abs.sc:REALMTerrestrial                                                                      
temptrend_abs.sc:tempave.sc                                                                            
temptrend_abs.sc:tempave_metab.sc                                                                      
temptrend_abs.sc:seas.sc                                                                               
temptrend_abs.sc:microclim.sc                                                                          
temptrend_abs.sc:mass.sc                                                                               
temptrend_abs.sc:speed.sc                                                                              
temptrend_abs.sc:lifespan.sc                                                                           
temptrend_abs.sc:consumerfrac.sc                                                                       
                                           tmptrnd_bs.sc:h. REALMM: REALMT: t_.:REALMM:
temptrend_abs.sc                                                                       
REALMMarine                                                                            
REALMTerrestrial                                                                       
tempave.sc                                                                             
tempave_metab.sc                                                                       
seas.sc                                                                                
microclim.sc                                                                           
mass.sc                                                                                
speed.sc                                                                               
lifespan.sc                                                                            
consumerfrac.sc                                                                        
endothermfrac.sc                                                                       
nspp.sc                                                                                
temptrend.sc                                                                           
thermal_bias.sc                                                                        
npp.sc                                                                                 
human.sc                                                                               
temptrend_abs.sc:REALMMarine                                                           
temptrend_abs.sc:REALMTerrestrial                                                      
temptrend_abs.sc:tempave.sc                                                            
temptrend_abs.sc:tempave_metab.sc                                                      
temptrend_abs.sc:seas.sc                                                               
temptrend_abs.sc:microclim.sc                                                          
temptrend_abs.sc:mass.sc                                                               
temptrend_abs.sc:speed.sc                                                              
temptrend_abs.sc:lifespan.sc                                                           
temptrend_abs.sc:consumerfrac.sc                                                       
 [ reached getOption("max.print") -- omitted 9 rows ]

Standardized Within-Group Residuals:
        Min          Q1         Med          Q3         Max 
-6.84526227 -0.37611694  0.04106594  0.54207414  6.16845392 

Number of Observations: 42586
Number of Groups: 
              STUDY_ID rarefyID %in% STUDY_ID 
                   218                  42586 

plot coefs for full Total and HM models

coefs2 <- summary(modTfullJbeta)$tTable
coefs3 <- summary(modTfullHorn)$tTable
varstoplot <- unique(c(rownames(coefs2), rownames(coefs3)))

rows1 <- which(!grepl('Intercept', varstoplot) | grepl(':', varstoplot)) # vars to plot in first graph
rows1_2 <- which(rownames(coefs2) %in% varstoplot[rows1]) # rows in coefs2
rows1_3 <- which(rownames(coefs3) %in% varstoplot[rows1]) # rows in coefs3
xlims1 <- range(c(coefs2[rows1_2,1] - coefs2[rows1_2,2], 
                  coefs2[rows1_2,1] + coefs2[rows1_2,2], 
                  coefs3[rows1_3,1] - coefs3[rows1_3,2], 
                  coefs3[rows1_3,1] + coefs3[rows1_3,2]))

cols <- c('black', 'grey') # for Jbeta and Horn models, respectively
offs1 <- 0.1 # offset vertically for the two models
offs2 <- 0.01 # offset vertically for the two models (plot 2)

par(las = 1, mai = c(0.5, 3, 0.1, 0.1))

plot(0,0, col = 'white', xlim=xlims1, ylim = c(1,length(rows1)), yaxt='n', xlab = '', ylab ='')
axis(2, at = length(rows1):1, labels = varstoplot[rows1], cex.axis = 0.7)
abline(v = 0, col = 'grey')
for(i in 1:length(rows1)){
  if(varstoplot[rows1[i]] %in% rownames(coefs2)){
    x = coefs2[rownames(coefs2) == varstoplot[rows1[i]], 1]
    se = coefs2[rownames(coefs2) == varstoplot[rows1[i]], 2]
    points(x, length(rows1) + 1 - i + offs1, pch = 16, col = cols[1])
    lines(x = c(x-se, x+se), y = c(length(rows1) + 1 - i + offs1, length(rows1) + 1 - i + offs1), col = cols[1])
  }
  if(varstoplot[rows1[i]] %in% rownames(coefs3)){
    x = coefs3[rownames(coefs3) == varstoplot[rows1[i]], 1]
    se = coefs3[rownames(coefs3) == varstoplot[rows1[i]], 2]
    points(x, length(rows1) + 1 - i - offs1, pch = 16, col = cols[2])
    lines(x = c(x-se, x+se), y = c(length(rows1) + 1 - i - offs1, length(rows1) + 1 - i - offs1), col = cols[2])
  }
}

NA
NA

Black is for Jaccard total turnover (pres/abs), grey is for Morisita-Horn turnover (considers abundance)

Plot coefficients from all full models

# fig.width = 3, fig.height = 5, out.height=2.5, out.width=3, fig.retina =3 for macbook screen
# double that for external monitor
coefs <- as.data.table(summary(modTfull1)$tTable)
coefs2 <- as.data.table(summary(modTfullJbeta)$tTable)
coefs3 <- as.data.table(summary(modTfullHorn)$tTable)

coefs$mod <- 'Jtu'
coefs2$mod <- 'Jbeta'
coefs3$mod <- 'Horn'

coefs$var <- rownames(summary(modTfull1)$tTable)
coefs2$var <- rownames(summary(modTfullJbeta)$tTable)
coefs3$var <- rownames(summary(modTfullHorn)$tTable)

# extract temperature effects and bind model coefs together
cols <- c('var', 'Value', 'Std.Error', 'mod')

allcoefsfull <- rbind(coefs[grep('temptrend|REALM', var), ..cols], 
                      coefs2[grep('temptrend|REALM', var), ..cols], 
                      coefs3[grep('temptrend|REALM', var), ..cols])
allcoefsfull$var[allcoefsfull$var == 'temptrend_abs.sc'] <- 'temptrend_abs.sc:REALMFreshwater'

# add average temperature effect (across realms) to realm-specific temperature effects
meantempeffect <- allcoefsfull[var == 'temptrend_abs.sc:REALMFreshwater', mean(Value), by = mod]$V1
allcoefsfull[var == 'temptrend_abs.sc:REALMMarine', Value := Value + meantempeffect]
allcoefsfull[var == 'temptrend_abs.sc:REALMTerrestrial', Value := Value + meantempeffect]

# add base temperature:human effect (freshwater) to realm-specific temperature:human effects
allcoefsfull$Value[allcoefsfull$var == 'temptrend_abs.sc:REALMMarine:human.sc'] <- with(allcoefsfull, Value[var == 'temptrend_abs.sc:REALMMarine:human.sc'] + Value[var == 'temptrend_abs.sc:human.sc'])
allcoefsfull$Value[allcoefsfull$var == 'temptrend_abs.sc:REALMTerrestrial:human.sc'] <- with(allcoefsfull, Value[var == 'temptrend_abs.sc:REALMTerrestrial:human.sc'] + Value[var == 'temptrend_abs.sc:human.sc'])


# remove non-temperature effects
allcoefsfull <- allcoefsfull[grepl(':', allcoefsfull$var) & grepl('temptrend', allcoefsfull$var), ]

# add info for plotting
allcoefsfull$lCI <- allcoefsfull$Value - allcoefsfull$Std.Error # lower confidence interval
allcoefsfull$uCI <- allcoefsfull$Value + allcoefsfull$Std.Error
nvar <- nrow(allcoefsfull)/3
allcoefsfull$y <- 1:nvar + rep(c(0, 0.1, 0.2), c(nvar, nvar, nvar)) # y-values

allcoefsfull$varname <- gsub('temptrend_abs.sc:|temptrend.sc:', '', allcoefsfull$var)
allcoefsfull$varname <- gsub('REALM', '', allcoefsfull$varname)
allcoefsfull$varname <- gsub('.sc', '', allcoefsfull$varname)
allcoefsfull$varname <- gsub('^human$', 'Freshwater:human', allcoefsfull$varname)

xlims1 <- c(0.0, 0.05) # for realms
xlims2 <- c(-0.01, 0.015) # for traits
xlims3 <- c(-0.004, 0.0025) # for environment
xlims4 <- c(-0.016, 0.005) # for community
xlims5 <- c(-0.01, 0.015) # for human

ddg <- 0.5 # dodge for each model

set1 <- c('Terrestrial', 'Marine', 'Freshwater')
set2 <- c('mass', 'speed', 'lifespan', 'consumerfrac', 'endothermfrac', 'tempave_metab')
set3 <- c('seas', 'microclim', 'tempave')
set4 <- c('npp', 'nspp', 'thermal_bias')
set5 <- c('Terrestrial:human', 'Marine:human', 'Freshwater:human')

p1 <- ggplot(subset(allcoefsfull, varname %in% set1), 
                    aes(varname, Value, group = mod, color = mod)) +
  geom_hline(yintercept = 0, linetype = 'dashed', color = 'light grey') +
  geom_errorbar(aes(ymin = lCI, ymax = uCI), width = 0, position = position_dodge(ddg)) + 
  geom_point(position = position_dodge(ddg)) + 
  labs(y = 'Temperature change effect', x = '', tag = 'A') +
  scale_color_grey() + 
  theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(),
        panel.background = element_blank(), axis.line = element_line(colour = "black"),
        legend.position='none',
        axis.text=element_text(size=7),
        axis.title=element_text(size=7)) + 
  coord_flip(ylim = xlims1)

p2 <- ggplot(subset(allcoefsfull, varname %in% set2), 
                    aes(varname, Value, group = mod, color = mod)) +
  geom_hline(yintercept = 0, linetype = 'dashed', color = 'light grey') +
  geom_errorbar(aes(ymin = lCI, ymax = uCI), width = 0, position = position_dodge(ddg)) + 
  geom_point(position = position_dodge(ddg)) + 
  labs(y = 'Interaction with temperature change effect', x = '', tag = 'B') +
  scale_color_grey() + 
  theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(),
        panel.background = element_blank(), axis.line = element_line(colour = "black"),
        legend.position='none',
        axis.text=element_text(size=7),
        axis.title=element_text(size=7)) + 
  coord_flip(ylim = xlims2)

p3 <- ggplot(subset(allcoefsfull, varname %in% set3), 
                    aes(varname, Value, group = mod, color = mod)) +
  geom_hline(yintercept = 0, linetype = 'dashed', color = 'light grey') +
  geom_errorbar(aes(ymin = lCI, ymax = uCI), width = 0, position = position_dodge(ddg)) + 
  geom_point(position = position_dodge(ddg)) + 
  labs(y = 'Interaction with temperature change effect', x = '', tag = 'C') +
  scale_color_grey() + 
  theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(),
        panel.background = element_blank(), axis.line = element_line(colour = "black"),
        legend.position='none',
        axis.text=element_text(size=7),
        axis.title=element_text(size=7)) + 
  coord_flip(ylim = xlims3)

p4 <- ggplot(subset(allcoefsfull, varname %in% set4), 
                    aes(varname, Value, group = mod, color = mod)) +
  geom_hline(yintercept = 0, linetype = 'dashed', color = 'light grey') +
  geom_errorbar(aes(ymin = lCI, ymax = uCI), width = 0, position = position_dodge(ddg)) + 
  geom_point(position = position_dodge(ddg)) + 
  labs(y = 'Interaction with temperature change effect', x = '', tag = 'D') +
  scale_color_grey() + 
  theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(),
        panel.background = element_blank(), axis.line = element_line(colour = "black"),
        legend.position='none',
        axis.text=element_text(size=7),
        axis.title=element_text(size=7)) + 
  coord_flip(ylim = xlims4)

p5 <- ggplot(subset(allcoefsfull, varname %in% set5), 
                    aes(varname, Value, group = mod, color = mod)) +
  geom_hline(yintercept = 0, linetype = 'dashed', color = 'light grey') +
  geom_errorbar(aes(ymin = lCI, ymax = uCI), width = 0, position = position_dodge(ddg)) + 
  geom_point(position = position_dodge(ddg)) + 
  labs(y = 'Interaction with temperature change effect', x = '', tag = 'E') +
  scale_color_grey() + 
  theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(),
        panel.background = element_blank(), axis.line = element_line(colour = "black"),
        legend.position='none',
        axis.text=element_text(size=7),
        axis.title=element_text(size=7)) + 
  coord_flip(ylim = xlims5)

grid.arrange(p1, p2, p3, p4, p5, ncol = 2, layout_matrix = rbind(c(1,2), c(3,4), c(5, NA)))

To do

LS0tCnRpdGxlOiAnRHJpdmVycyBvZiB2YXJpYXRpb24gaW4gdGhlIGNvbW11bml0eSByZXNwb25zZSB0byB0ZW1wZXJhdHVyZSBjaGFuZ2UgYWNyb3NzIHJlYWxtcycKc3VidGl0bGU6ICcodXNpbmcgbWl4ZWQgZWZmZWN0cyBtb2RlbHMpJwpvdXRwdXQ6IAogICAgZ2l0aHViX2RvY3VtZW50OiBkZWZhdWx0CiAgICAjaHRtbF9kb2N1bWVudDogZGVmYXVsdAogICAgaHRtbF9ub3RlYm9vazogZGVmYXVsdAotLS0KCkNvbGxhYm9yYXRvcnM6IFNoYW5lIEJsb3dlcywgSm9uIENoYXNlLCBIZWxtdXQgSGlsbGVicmFuZCwgTWljaGFlbCBCdXJyb3dzLCBBbWFuZGEgQmF0ZXMsIFVsaSBCcm9zZSwgQmVub2l0IEdhdXplbnMsIExhdXJhIEFudGFvCkFzc2lzdGFuY2U6IEthdGhlcmluZSBMZXcsIEpvc2VmIEhhdXNlcgoKIyBJbnRyb2R1Y3Rpb24KLSBDbGltYXRlIGNoYW5nZSBpcyBkcml2aW5nIGEgd2lkZXNwcmVhZCByZW9yZ2FuaXphdGlvbiBvZiBlY29sb2dpY2FsIGNvbW11bml0aWVzIGFyb3VuZCB0aGUgd29ybGQgKFBhcm1zZXNhbiAmIFlvaGUgMjAwMywgUG9sb2N6YW5za2EgZXQgYWwuIDIwMTMpLAotIGJ1dCB0aGUgaW1wYWN0cyBvZiBjbGltYXRlIGNoYW5nZSB2YXJ5IHN1YnN0YW50aWFsbHkgZnJvbSBvbmUgbG9jYXRpb24gdG8gYW5vdGhlciBhbmQgYW1vbmcgdGF4YSAoTW9saW5vcyBldCBhbC4gMjAxNiBOQ0MsIEFudGFvIGV0IGFsLiAyMDIwIE5FRSkuCi0gQ29tbXVuaXR5IHJlb3JnYW5pemF0aW9uIGlzIHN1YnN0YW50aWFsbHkgbW9yZSBjb21tb24gdGhhbiBhbiBhZ2dyZWdhdGUgbG9zcyBvciBnYWluIG9mIHNwZWNpZXMgKERvcm5lbGFzIGV0IGFsLiAyMDE0IFNjaWVuY2UsIEJsb3dlcyBldCBhbC4gMjAxOSBTY2llbmNlLCBIaWxsZWJyYW5kIGV0IGFsLiAyMDE3IEogQXBwbCBFY29sKQotIFRoZXJlIGFyZSBtYW55IGh5cG90aGVzZXMgZm9yIHdoeSBzb21lIGNvbW11bml0aWVzIGFyZSBtb3JlIHNlbnNpdGl2ZSB0byB3YXJtaW5nIHRoYW4gb3RoZXJzLCBpbmNsdWRpbmcgZGlmZmVyZW5jZXMgaW4KICAtIG1ldGFib2xpYyByYXRlcyAoRGlsbG9uIGV0IGFsLiAyMDEwIE5hdHVyZSksIAogIC0gdGhlcm1hbCBwaHlzaW9sb2d5IChEZXV0c2NoIGV0IGFsLiAyMDA4IFBOQVMsIFBpbnNreSBldCBhbC4gMjAxOSBOYXR1cmUpLCAKICAtIG1pY3JvY2xpbWF0ZSBhdmFpbGFiaWxpdHkgKEJ1cnJvd3MgZXQgYWwuIDIwMTkgTkNDLCBTdWdnaXR0IGV0IGFsLiAyMDE4IE5DQyksCiAgLSBzcGVjaWVzIG1vYmlsaXR5IChQb2xvY3phbnNrYSBldCBhbC4gMjAxMyBOQ0MsIEJ1cnJvd3MgZXQgYWwuIDIwMTEgU2NpZW5jZSwgU3VuZGF5IGV0IGFsLiAyMDEyIE5DQykKICAtIG9yIGdlbmVyYXRpb24gdGltZSAoQmVhdWdyYW5kIGV0IGFsLiAyMDA5IERTUiBJSSwgUG9sb2N6YW5za2EgZXQgYWwuIDIwMTMgTkNDKSwKICAtIGNvbnN1bWVycyB2cy4gcHJvZHVjZXJzIChQZXRjaGV5IGV0IGFsLiAxOTk5IE5hdHVyZSkKICAtIGNvbW11bml0eSBjb21wb3NpdGlvbiAoU3R1YXJ0LVNtaXRoIGV0IGFsLiAyMDE1IE5hdHVyZSwgQmVhdWdyYW5kIGV0IGEuIDIwMTUgTkNDLCBUcmlzb3MgZXQgYWwuIDIwMjAgTmF0dXJlKSwgCiAgLSBlY29zeXN0ZW0gcHJvZHVjdGl2aXR5IChUaG9tYXMgZXQgYWwuIDIwMTcgR0NCLCBCcmV0dCAxOTcxIEFtIFpvbyksCiAgLSBleHBvc3VyZSB0byBodW1hbiBpbXBhY3RzIChXaGl0ZSAmIEtlcnIgMjAwNiBFY29ncmFwaHkpCiAgLSBhbmQgYW1vbmcgcmVhbG1zIChBbnRhbyBldCBhbC4gMjAyMCBORUUpLgotIFNjYWxpbmcgdXAgZnJvbSBvcmdhbmlzbWFsIGVmZmVjdHMgdG8gd2hvbGUgZWNvbG9naWNhbCBjb21tdW5pdGllcyBpcyBjb21wbGV4LCBhbmQgeWV0IHRoZXNlIHNjYWxlcyBhcmUgY3JpdGljYWwgZm9yIGVjb3N5c3RlbSBmdW5jdGlvbmluZyBhbmQgaHVtYW4gd2VsbC1iZWluZy4gCi0gVGhlcmUgaXMgYSBuZWVkIGZvciBhIGNvbXByZWhlbnNpdmUgdGVzdCB0byB1bmRlcnN0YW5kIHdoZXJlIHdhcm1pbmcgaXMgZHJpdmluZyBhbmQgaXMgbGlrZWx5IHRvIGRyaXZlIHRoZSBtb3N0IGRyYW1hdGljIGNvbW11bml0eSB0dXJub3ZlcgoKIyBNZXRob2RzCi0gQmlvVGltZSBkYXRhc2V0LCBncmlkZGVkIHRvIDk2IGttMiBoZXhhZ29ucywgc3VtbWFyaXplZCBhcyB0ZW1wb3JhbCB0dXJub3ZlciAoQmxvd2VzKQogIC0gVGVtcG9yYWwgc2xvcGUgb2YgSmFjY2FyZCB0dXJub3ZlciBjb21wYXJlZCB0byB0aGUgZmlyc3QgeWVhcgogIC0gU2FtZSBmb3IgSmFjY2FyZCB0b3RhbAogIC0gYW5kIE1vcmlzaXRhLUhvcm4gdHVybm92ZXIKLSBUZXN0ZWQgZXhwbGFuYXRvcnkgdmFyaWFibGVzIGZvciBkaWZmZXJlbmNlcyBpbiByYXRlIG9mIHR1cm5vdmVyOgogIC0gVGVtcGVyYXR1cmUgdHJlbmQgb3ZlciB0aGUgdGltZS1mcmFtZSBvZiBlYWNoIHRpbWUtc2VyaWVzIChDUlUgVFMgNC4wMyBvbiBsYW5kIGFuZCBpbiBmcmVzaHdhdGVyLCBFUlNTVCB2NSBpbiB0aGUgb2NlYW4pCiAgLSBTZWFzb25hbGl0eSBhcyBhIG1ldHJpYyBvZiB0aGVybWFsIHNlbnNpdGl2aXR5IChEZXV0c2NoIGV0IGFsLiAyMDA4IFBOQVMpLiBTdGFuZGFyZCBkZXZpYXRpb24gb2YgbW9udGhseSB0ZW1wZXJhdHVyZXMuCiAgLSBBdmVyYWdlIHRlbXBlcmF0dXJlIGFzIGEgbWV0cmljIG9mIG1ldGFib2xpYyByYXRlcyAoRGlsbG9uIGV0IGFsLiAyMDEwIE5hdHVyZSwgQW50YW8gZXQgYWwuIDIwMjAgTmF0IEUmRSkKICAtIE1vYmlsaXR5IGNhbGN1bGF0ZWQgZnJvbSBib2R5IG1hc3MgYW5kIHRheG9ub21pYyBncm91cCBjbGFzc2lmaWNhdGlvbnMgb2YgbW9iaWxpdHkgbW9kZSAoZmx5LCBydW4sIHN3aW0sIGNyYXdsLCBzZXNzaWxlKS4gRmx5L3J1bi9zd2ltIGZvbGxvd2VkIHRoZSBhbGxvbWV0cmljIHJlbGF0aW9uc2hpcCBpbiBIaXJ0IGV0IGFsLiAyMDE3IE5hdCBFJkUuIENyYXdsIHNldCBhdCAwLjEga20vaHIsIHNlc3NpbGUgc2V0IHRvIDAga20vaHIuIFRoZW4gY2FsY3VsYXRlZCBhdmVyYWdlZCB3aXRoaW4gZWFjaCBhc3NlbWJsYWdlLgogIC0gTmV0IHByaW1hcnkgcHJvZHVjdGl2aXR5IChOUFApIGZyb20gdGhlIG1lcmdlZCBsYW5kL29jZWFuIHByb2R1Y3QgcHJvZHVjZWQgYnkgdGhlIFtPY2VhbiBQcm9kdWN0aXZpdHldKGh0dHA6Ly93d3cuc2NpZW5jZS5vcmVnb25zdGF0ZS5lZHUvb2NlYW4ucHJvZHVjdGl2aXR5LykgZ3JvdXAgYXQgT3JlZ29uIFN0YXRlIHVzaW5nIG1ldGhvZHMgZnJvbSBaaGFvIGV0IGFsLiAyMDA1IGFuZCBCZWhyZW5mZWxkICYgRmFsa293c2tpIDE5OTcuIAogLSBUTyBETzoKICAgLSBHZW5lcmF0aW9uIHRpbWUgY2FsY3VsYXRlZCBmcm9tIGJvZHkgbWFzcyBhbmQgZW5kb3RoZXJtIHZzLiBlY3RvdGhlcm0gY2xhc3NpZmljYXRpb25zLCBmb2xsb3dpbmcgTWNDb3kgJiBHaWxsb29seSAyMDA4IEVMRS4gQXZlcmFnZWQgYWNyb3NzIHNwZWNpZXMgd2l0aGluIGVhY2ggYXNzZW1ibGFnZS4gCiAgIC0gSHVtYW4gaW1wYWN0IGNhbGN1bGF0ZWQgZnJvbSBDYXJzdGVuIE1leWVyJ3MgZWNvc3lzdGVtIGN1YmUgZGF0YQogICAtIFRoZXJtYWwgYmlhcyBjYWxjdWxhdGVkIGZyb20gU3BlY2llcyBUZW1wZXJhdHVyZSBJbmRpY2VzIChNaWtlIEJ1cnJvd3MpCiAgIC0gTWljcm9jbGltYXRlcyBjYWxjdWxhdGVkIGZyb20gV29ybGRDbGltIGFuZCBCaW9PcmFjbGUgKExhdXJhIEFudGFvKQogICAtIENvbnN1bWVyIHZzLiBwcm9kdWNlciBjbGFzc2lmaWNhdGlvbgogLSBNYXliZSB0byBkbzoKICAgLSBTcGVjaWVzIHBvb2wgcmljaG5lc3MKLSBEaWZmZXJlbmNlcyBpbiB0ZW1wb3JhbCB0dXJub3ZlciAocmVzcG9uc2UgdmFyaWFibGUpIG1vZGVsZWQgd2l0aCBhIGxpbmVhciBtaXhlZCBlZmZlY3RzIG1vZGVsIChubG1lIHBhY2thZ2UsIGxtZSgpIGZ1bmN0aW9uKS4gU2VlIGJlbG93IGZvciBkZXRhaWxzLgoKYGBge3Igc2V0dXB9CmxpYnJhcnkoZGF0YS50YWJsZSkgIyBmb3IgaGFuZGxpbmcgbGFyZ2UgZGF0YXNldHMKbGlicmFyeShnZ3Bsb3QyKSAjIGZvciBzb21lIHBsb3R0aW5nCmxpYnJhcnkobmxtZSkgIyBmb3IgTUUgbW9kZWxzCmxpYnJhcnkoYmVhbnBsb3QpICMgZm9yIGJlYW5wbG90cwpsaWJyYXJ5KG1hcHMpICMgZm9yIG1hcApsaWJyYXJ5KGdyaWRFeHRyYSkgIyB0byBjb21iaW5lIGdncGxvdHMgdG9nZXRoZXIKbGlicmFyeShncmlkKSAjIHRvIGNvbWJpbmUgZ2dwbG90cyB0b2dldGhlcgoKb3B0aW9ucyh3aWR0aD01MDApICMgdHVybiBvZmYgbW9zdCB0ZXh0IHdyYXBwaW5nCgojIHRlbGwgUlN0dWRpbyB0byB1c2UgcHJvamVjdCByb290IGRpcmVjdG9yeSBhcyB0aGUgcm9vdCBmb3IgdGhpcyBub3RlYm9vay4gTmVlZGVkIHNpbmNlIHdlIGFyZSBzdG9yaW5nIGNvZGUgaW4gYSBzZXBhcmF0ZSBkaXJlY3RvcnkuCmtuaXRyOjpvcHRzX2tuaXQkc2V0KHJvb3QuZGlyID0gcnByb2pyb290OjpmaW5kX3JzdHVkaW9fcm9vdF9maWxlKCkpIApgYGAKCmBgYHtyIGxvYWQgZGF0YX0KIyBUdXJub3ZlciBhbmQgY292YXJpYXRlcyBhc3NlbWJsZWQgYnkgdHVybm92ZXJfdnNfdGVtcGVyYXR1cmVfcHJlcC5SbWQKdHJlbmRzIDwtIGZyZWFkKCdvdXRwdXQvdHVybm92ZXJfd19jb3ZhcmlhdGVzLmNzdi5neicpCgojIHNldCByZWFsbSBvcmRlcgp0cmVuZHNbLCBSRUFMTSA6PSBmYWN0b3IoUkVBTE0sIGxldmVscyA9IGMoJ0ZyZXNod2F0ZXInLCAnTWFyaW5lJywgJ1RlcnJlc3RyaWFsJyksIG9yZGVyZWQgPSBGQUxTRSldCgojIHJlYWxtIHRoYXQgY29tYmluZWQgVGVycmVzdHJpYWwgYW5kIEZyZXNod2F0ZXIsIGZvciBpbnRlcmFjdGluZyB3aXRoIGh1bWFuIGltcGFjdAp0cmVuZHNbLCBSRUFMTTIgOj0gUkVBTE1dCmxldmVscyh0cmVuZHMkUkVBTE0yKSA9IGxpc3QoVGVyckZyZXNoID0gIkZyZXNod2F0ZXIiLCBUZXJyRnJlc2ggPSAiVGVycmVzdHJpYWwiLCBNYXJpbmUgPSAiTWFyaW5lIikKCiMgZ3JvdXAgTWFyaW5lIGludmVydGVicmF0ZXMvcGxhbnRzIGluIHdpdGggQWxsCnRyZW5kc1ssIHRheGFfbW9kMiA6PSB0YXhhX21vZF0KdHJlbmRzW3RheGFfbW9kID09ICdNYXJpbmUgaW52ZXJ0ZWJyYXRlcy9wbGFudHMnLCB0YXhhX21vZDIgOj0gJ0FsbCddCmBgYAoKTG9nLXRyYW5zZm9ybSBzb21lIHZhcmlhYmxlcywgdGhlbiBjZW50ZXIgYW5kIHNjYWxlLiAKYGBgIHtyIGNlbnRlciBhbmQgc2NhbGV9CnRyZW5kc1ssIHRlbXBhdmUuc2MgOj0gc2NhbGUodGVtcGF2ZSldCnRyZW5kc1ssIHRlbXBhdmVfbWV0YWIuc2MgOj0gc2NhbGUodGVtcGF2ZV9tZXRhYildCnRyZW5kc1ssIHNlYXMuc2MgOj0gc2NhbGUoc2VhcyldCnRyZW5kc1ssIG1pY3JvY2xpbS5zYyA6PSBzY2FsZShsb2cobWljcm9jbGltKSldCnRyZW5kc1ssIHRlbXB0cmVuZC5zYyA6PSBzY2FsZSh0ZW1wdHJlbmQpXQp0cmVuZHNbLCB0ZW1wdHJlbmRfYWJzLnNjIDo9IHNjYWxlKGFicyh0ZW1wdHJlbmQpKV0KdHJlbmRzWywgbnBwLnNjIDo9IHNjYWxlKGxvZyhucHApKV0KdHJlbmRzWywgbWFzcy5zYyA6PSBzY2FsZShsb2cobWFzc19tZWFuX3dlaWdodCkpXQp0cmVuZHNbLCBzcGVlZC5zYyA6PSBzY2FsZShsb2coc3BlZWRfbWVhbl93ZWlnaHQrMSkpXQp0cmVuZHNbLCBsaWZlc3Bhbi5zYyA6PSBzY2FsZShsb2cobGlmZXNwYW5fbWVhbl93ZWlnaHQpKV0KdHJlbmRzWywgdGhlcm1hbF9iaWFzLnNjIDo9IHNjYWxlKHRoZXJtYWxfYmlhcyldCnRyZW5kc1ssIGNvbnN1bWVyZnJhYy5zYyA6PSBzY2FsZShjb25zZnJhYyldCnRyZW5kc1ssIGVuZG90aGVybWZyYWMuc2MgOj0gc2NhbGUoZW5kb2ZyYWMpXQp0cmVuZHNbLCBuc3BwLnNjIDo9IHNjYWxlKGxvZyhOc3BwKSldCnRyZW5kc1ssIGh1bWFuLnNjIDo9IHNjYWxlKGh1bWFuKV0KYGBgCgojIyMgRG8gdGhlIHZhcmlhYmxlcyBsb29rIG9rPwpgYGB7ciBoaXN0b2dyYW1zfQojIGhpc3RvZ3JhbXMgdG8gZXhhbWluZQpjZXhtYWluID0gMC42CnBhcihtZnJvdyA9IGMoMyw1KSkKaW52aXNpYmxlKHRyZW5kc1ssIGhpc3QodGVtcGF2ZS5zYywgbWFpbiA9ICdFbnZpcm9ubWVudGFsIHRlbXBlcmF0dXJlICjCsEMpJywgY2V4Lm1haW4gPSBjZXhtYWluKV0pCmludmlzaWJsZSh0cmVuZHNbLCBoaXN0KHRlbXBhdmVfbWV0YWIuc2MsIG1haW4gPSAnTWV0YWJvbGljIHRlbXBlcmF0dXJlICjCsEMpJywgY2V4Lm1haW4gPSBjZXhtYWluKV0pCmludmlzaWJsZSh0cmVuZHNbLCBoaXN0KHNlYXMuc2MsIG1haW4gPSAnU2Vhc29uYWxpdHkgKMKwQyknLCBjZXgubWFpbiA9IGNleG1haW4pXSkKaW52aXNpYmxlKHRyZW5kc1ssIGhpc3QobWljcm9jbGltLnNjLCBtYWluID0gJ2xvZyBNaWNyb2NsaW1hdGVzICjCsEMpJywgY2V4Lm1haW4gPSBjZXhtYWluKV0pCmludmlzaWJsZSh0cmVuZHNbLCBoaXN0KHRlbXB0cmVuZC5zYywgbWFpbiA9ICdUZW1wZXJhdHVyZSB0cmVuZCAowrBDL3lyKScsIGNleC5tYWluID0gY2V4bWFpbildKQppbnZpc2libGUodHJlbmRzWywgaGlzdCh0ZW1wdHJlbmRfYWJzLnNjLCBtYWluID0gJ2xvZyBhYnMoVGVtcGVyYXR1cmUgdHJlbmQpICjCsEMveXIpJywgY2V4Lm1haW4gPSBjZXhtYWluKV0pCmludmlzaWJsZSh0cmVuZHNbLCBoaXN0KG1hc3Muc2MsIG1haW4gPSAnbG9nIE1hc3MgKGcpJywgY2V4Lm1haW4gPSBjZXhtYWluKV0pCmludmlzaWJsZSh0cmVuZHNbLCBoaXN0KHNwZWVkLnNjLCBtYWluID0gJ2xvZyBTcGVlZCAoa20vaHIpJywgY2V4Lm1haW4gPSBjZXhtYWluKV0pCmludmlzaWJsZSh0cmVuZHNbLCBoaXN0KGxpZmVzcGFuLnNjLCBtYWluID0gJ2xvZyBMaWZlc3BhbiAoeXIpJywgY2V4Lm1haW4gPSBjZXhtYWluKV0pCmludmlzaWJsZSh0cmVuZHNbLCBoaXN0KGNvbnN1bWVyZnJhYy5zYywgbWFpbiA9ICdDb25zdW1lcnMgKGZyYWN0aW9uKScsIGNleC5tYWluID0gY2V4bWFpbildKQppbnZpc2libGUodHJlbmRzWywgaGlzdChlbmRvdGhlcm1mcmFjLnNjLCBtYWluID0gJ0VuZG90aGVybXMgKGZyYWN0aW9uKScsIGNleC5tYWluID0gY2V4bWFpbildKQppbnZpc2libGUodHJlbmRzWywgaGlzdChuc3BwLnNjLCBtYWluID0gJ2xvZyBTcGVjaWVzIHJpY2huZXNzJywgY2V4Lm1haW4gPSBjZXhtYWluKV0pCmludmlzaWJsZSh0cmVuZHNbLCBoaXN0KHRoZXJtYWxfYmlhcy5zYywgbWFpbiA9ICdUaGVybWFsIGJpYXMgKMKwQyknLCBjZXgubWFpbiA9IGNleG1haW4pXSkKaW52aXNpYmxlKHRyZW5kc1ssIGhpc3QobnBwLnNjLCBtYWluID0gJ2xvZyBOZXQgcHJpbWFyeSBwcm9kdWN0aXZpdHknLCBjZXgubWFpbiA9IGNleG1haW4pXSkKaW52aXNpYmxlKHRyZW5kc1ssIGhpc3QoaHVtYW4uc2MsIG1haW4gPSAnSHVtYW4gaW1wYWN0IHNjb3JlJywgY2V4Lm1haW4gPSBjZXhtYWluKV0pCgpgYGAKCiMjIyBDaGVjayBjb3JyZWxhdGlvbnMgYW1vbmcgdmFyaWFibGVzLiBQZWFyc29uJ3MgciBpcyBvbiB0aGUgbG93ZXIgZGlhZ29uYWwuCmBgYHtyIHBhaXJzLCBmaWcuaGVpZ2h0PTEwLCBmaWcud2lkdGg9MTB9CnBhbmVsLmNvciA8LSBmdW5jdGlvbih4LCB5LCBkaWdpdHMgPSAyLCBwcmVmaXggPSAiIiwgY2V4LmNvciwgLi4uKQp7CiAgICB1c3IgPC0gcGFyKCJ1c3IiKTsgb24uZXhpdChwYXIodXNyKSkKICAgIHBhcih1c3IgPSBjKDAsIDEsIDAsIDEpKQogICAgciA8LSBjb3IoeCwgeSwgdXNlID0gJ3BhaXJ3aXNlLmNvbXBsZXRlLm9icycpCiAgICB0eHQgPC0gZm9ybWF0KGMociwgMC4xMjM0NTY3ODkpLCBkaWdpdHMgPSBkaWdpdHMpWzFdCiAgICB0eHQgPC0gcGFzdGUwKHByZWZpeCwgdHh0KQogICAgaWYobWlzc2luZyhjZXguY29yKSkgY2V4LmNvciA8LSAwLjgvc3Ryd2lkdGgodHh0KQogICAgdGV4dCgwLjUsIDAuNSwgdHh0KSAjLCBjZXggPSBjZXguY29yICogcikKfQpwYWlycyhmb3JtdWxhID0gfiBSRUFMTSArIHRlbXBhdmUuc2MgKyB0ZW1wYXZlX21ldGFiLnNjICsgc2Vhcy5zYyArIG1pY3JvY2xpbS5zYyArIHRlbXB0cmVuZC5zYyArIHRlbXB0cmVuZF9hYnMuc2MgKyAgbWFzcy5zYyArIHNwZWVkLnNjICsgbGlmZXNwYW4uc2MgKyBjb25zdW1lcmZyYWMuc2MgKyBlbmRvdGhlcm1mcmFjLnNjICsgbnNwcC5zYyArIHRoZXJtYWxfYmlhcy5zYyArIG5wcC5zYyArIGh1bWFuLnNjLCBkYXRhID0gdHJlbmRzLCBnYXAgPSAxLzEwLCBjZXggPSAwLjIsIGNvbCA9ICcjMDAwMDAwMjInLCBsb3dlci5wYW5lbCA9IHBhbmVsLmNvcikKCmBgYAoKTWFzcyBhbmQgbGlmZXNwYW4gbG9vayB0aWdodGx5IGNvcnJlbGF0ZWQsIGJ1dCByIG9ubHkgMC41Ni4uLj8KVGVtcGF2ZV9tZXRhYiBhbmQgbGlmZXNwYW4gZG9uJ3QgbG9vayB0aWdodGx5IGNvcnJlbGF0ZWQsIGJ1dCByPSAtMC44MSAKVGVtcGF2ZV9tZXRhYiBhbmQgc3BlZWQgZG9uJ3QgbG9vayB0aWdodGx5IGNvcnJlbGF0ZWQsIGJ1dCByPSAtMC44MyAKTGlmZXNwYW4gYW5kIHNwZWVkIGRvbid0IGxvb2sgdGlnaHRseSBjb3JyZWxhdGVkLCBidXQgciA9IDAuNzMKCgojIyMgRXhhbWluZSBob3cgbWFueSBkYXRhIHBvaW50cyBhcmUgYXZhaWxhYmxlCkp1c3QgdHVybm92ZXIKYGBge3Igc2FtcGxlIHNpemUgYWxsfQpjYXQoJ092ZXJhbGwgIyB0aW1lLXNlcmllczogJywgbnJvdyh0cmVuZHMpLCAnXG4nKQpjYXQoJyMgc3R1ZGllczogJywgdHJlbmRzWywgbGVuZ3RoKHVuaXF1ZShTVFVEWV9JRCkpXSwgJ1xuJykKY2F0KCdEYXRhIHBvaW50czogJywgdHJlbmRzWywgc3VtKG55ckJUKV0sICdcbicpCnRyZW5kc1ssIHRhYmxlKFJFQUxNKV0KdHJlbmRzWywgdGFibGUodGF4YV9tb2QpXQp0cmVuZHNbLCB0YWJsZSh0YXhhX21vZCwgUkVBTE0pXQpgYGAKCldpdGggYWxsIGNvdmFyaWF0ZXMKYGBge3Igc2FtcGxlIHNpemUgZm9yIEphY2NhcmQgdHVybm92ZXJ9CiMgdGhlIGNhc2VzIHdlIGNhbiBjb21wYXJlCmFwcGx5KHRyZW5kc1ssIC4oSnR1dHJlbmQsIFJFQUxNLCB0ZW1wYXZlLnNjLCB0ZW1wYXZlX21ldGFiLnNjLCBzZWFzLnNjLCBtaWNyb2NsaW0uc2MsIHRlbXB0cmVuZC5zYywgbWFzcy5zYywgc3BlZWQuc2MsIGxpZmVzcGFuLnNjLCBjb25zdW1lcmZyYWMuc2MsIGVuZG90aGVybWZyYWMuc2MsIG5zcHAuc2MsIHRoZXJtYWxfYmlhcy5zYywgbnBwLnNjLCBodW1hbi5zYyldLCBNQVJHSU4gPSAyLCBGVU4gPSBmdW5jdGlvbih4KSBzdW0oIWlzLm5hKHgpKSkKaSA8LSB0cmVuZHNbLCBjb21wbGV0ZS5jYXNlcyhKdHV0cmVuZCwgdGVtcHRyZW5kLnNjLCB0ZW1wYXZlX21ldGFiLnNjLCBSRUFMTSwgc2Vhcy5zYywgbWljcm9jbGltLnNjLCBucHAuc2MsIG1hc3Muc2MsIHNwZWVkLnNjLCBsaWZlc3Bhbi5zYywgY29uc3VtZXJmcmFjLnNjLCB0aGVybWFsX2JpYXMuc2MpXQpjYXQoJ092ZXJhbGwgIyB0aW1lLXNlcmllczogJywgc3VtKGkpLCAnXG4nKQpjYXQoJyMgc3R1ZGllczogJywgdHJlbmRzW2ksIGxlbmd0aCh1bmlxdWUoU1RVRFlfSUQpKV0sICdcbicpCmNhdCgnRGF0YSBwb2ludHM6ICcsIHRyZW5kc1tpLCBzdW0obnlyQlQpXSwgJ1xuJykKdHJlbmRzW2ksIHRhYmxlKFJFQUxNKV0KdHJlbmRzW2ksIHRhYmxlKHRheGFfbW9kKV0KdHJlbmRzW2ksIHRhYmxlKHRheGFfbW9kLCBSRUFMTSldCmBgYAoKIyMjIENob29zZSB0aGUgdmFyaWFuY2Ugc3RydWN0dXJlIGZvciBtaXhlZCBlZmZlY3RzIG1vZGxlcwpUcnkgY29tYmluYXRpb25zIG9mCgotIHZhcmlhbmNlIHNjYWxlZCB0byBhIHBvd2VyIG9mIHRoZSBudW1iZXIgb2YgeWVhcnMgaW4gdGhlIGNvbW11bml0eSB0aW1lLXNlcmllcwotIHZhcmlhbmNlIHNjYWxlZCB0byBhIHBvd2VyIG9mIHRoZSBhYnMgdGVtcGVyYXR1cmUgdHJlbmQKLSByYW5kb20gaW50ZXJjZXB0IGZvciB0YXhhX21vZAotIHJhbmRvbSBpbnRlcmNlcHQgZm9yIFNUVURZX0lECi0gcmFuZG9tIHNsb3BlIChhYnMgdGVtcGVyYXR1cmUgdHJlbmQpIGZvciB0YXhhX21vZAotIHJhbmRvbSBzbG9wZSAoYWJzIHRlbXBlcmF0dXJlIHRyZW5kKSBmb3IgU1RVRFlfSUQKLSByYW5kb20gaW50ZXJjZXB0IGZvciByYXJlZnlJRCAoZm9yIG92ZXJkaXNwZXJzaW9uKQoKQW5kIGNob29zZSB0aGUgb25lIHdpdGggbG93ZXN0IEFJQyAobm90IHJ1bjogdGFrZXMgYSBsb25nIHRpbWUpCmBgYHtyIGNob29zZSB2YXJpYW5jZSBzdHJ1Y3R1cmUgZm9yIEphY2FyZCB0dXJub3ZlciwgZXZhbCA9IEZBTFNFfQojIGZpdCBtb2RlbHMgZm9yIHZhcmlhbmNlIHN0cnVjdHVyZQpmaXhlZCA8LSBmb3JtdWxhKEp0dXRyZW5kIH4gUkVBTE0gKyB0ZW1wYXZlX21ldGFiLnNjICsgc2Vhcy5zYyArIG1pY3JvY2xpbS5zYyArIG5wcC5zYyArIHRlbXB0cmVuZF9hYnMuc2MgKwogICAgICAgICAgICAgICAgICAgICBtYXNzLnNjICsgc3BlZWQuc2MgKyBsaWZlc3Bhbi5zYyArIGNvbnN1bWVyZnJhYy5zYyArIHRoZXJtYWxfYmlhcy5zYykKaSA8LSB0cmVuZHNbLCBjb21wbGV0ZS5jYXNlcyhKdHV0cmVuZCwgUkVBTE0sIHRlbXBhdmVfbWV0YWIuc2MsIHNlYXMuc2MsIG1pY3JvY2xpbS5zYywgbnBwLnNjLCB0ZW1wdHJlbmRfYWJzLnNjLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hc3Muc2MsIHNwZWVkLnNjLCBsaWZlc3Bhbi5zYywgY29uc3VtZXJmcmFjLnNjLCB0aGVybWFsX2JpYXMuc2MpXQptb2RzIDwtIHZlY3RvcignbGlzdCcsIDApCm1vZHNbWzFdXSA8LSBnbHMoZml4ZWQsIGRhdGEgPSB0cmVuZHNbaSxdKQptb2RzW1syXV0gPC0gZ2xzKGZpeGVkLCBkYXRhID0gdHJlbmRzW2ksXSwgd2VpZ2h0cyA9IHZhclBvd2VyKC0wLjUsIH5ueXJCVCkpCm1vZHNbWzNdXSA8LSBnbHMoZml4ZWQsIGRhdGEgPSB0cmVuZHNbaSxdLCB3ZWlnaHRzID0gdmFyUG93ZXIoMC41LCB+IGFicyh0ZW1wdHJlbmQpKSkKCm1vZHNbWzRdXSA8LSBsbWUoZml4ZWQsIGRhdGEgPSB0cmVuZHNbaSxdLCByYW5kb20gPSB+MXx0YXhhX21vZDIsIGNvbnRyb2wgPSBsbWVDb250cm9sKG9wdCA9ICJvcHRpbSIpKQptb2RzW1s1XV0gPC0gbG1lKGZpeGVkLCBkYXRhID0gdHJlbmRzW2ksXSwgcmFuZG9tID0gfjF8U1RVRFlfSUQsIGNvbnRyb2wgPSBsbWVDb250cm9sKG9wdCA9ICJvcHRpbSIpKQptb2RzW1s2XV0gPC0gbG1lKGZpeGVkLCBkYXRhID0gdHJlbmRzW2ksXSwgcmFuZG9tID0gfjF8dGF4YV9tb2QyL1NUVURZX0lELCBjb250cm9sID0gbG1lQ29udHJvbChvcHQgPSAib3B0aW0iKSkKbW9kc1tbN11dIDwtIGxtZShmaXhlZCwgZGF0YSA9IHRyZW5kc1tpLF0sIHJhbmRvbSA9IH4xfFNUVURZX0lEL3JhcmVmeUlELCBjb250cm9sID0gbG1lQ29udHJvbChvcHQgPSAib3B0aW0iKSkKbW9kc1tbOF1dIDwtIGxtZShmaXhlZCwgZGF0YSA9IHRyZW5kc1tpLF0sIHJhbmRvbSA9IH4xfHRheGFfbW9kMi9TVFVEWV9JRC9yYXJlZnlJRCwgY29udHJvbCA9IGxtZUNvbnRyb2wob3B0ID0gIm9wdGltIikpCgptb2RzW1s5XV0gPC0gbG1lKGZpeGVkLCBkYXRhID0gdHJlbmRzW2ksXSwgcmFuZG9tID0gfnRlbXB0cmVuZF9hYnMuc2MgfCB0YXhhX21vZCkKbW9kc1tbMTBdXSA8LSBsbWUoZml4ZWQsIGRhdGEgPSB0cmVuZHNbaSxdLCByYW5kb20gPSB+dGVtcHRyZW5kX2Ficy5zYyB8IFNUVURZX0lEKQptb2RzW1sxMV1dIDwtIGxtZShmaXhlZCwgZGF0YSA9IHRyZW5kc1tpLF0sIHJhbmRvbSA9IH50ZW1wdHJlbmRfYWJzLnNjIHwgdGF4YV9tb2QyL1NUVURZX0lELCBjb250cm9sID0gbG1lQ29udHJvbChvcHQgPSAib3B0aW0iKSkKbW9kc1tbMTJdXSA8LSBsbWUoZml4ZWQsIGRhdGEgPSB0cmVuZHNbaSxdLCByYW5kb20gPSBsaXN0KFNUVURZX0lEID0gfiB0ZW1wdHJlbmRfYWJzLnNjLCByYXJlZnlJRCA9IH4xKSkgIyBpbmNsdWRlcyBvdmVyZGlzcGVyc2lvbi4gbmV3IGZvcm11bGEgc28gdGhhdCByYW5kb20gc2xvcGUgaXMgb25seSBmb3Igc3R1ZHkgbGV2ZWwgKG5vdCBlbm91Z2ggZGF0YSB0byBleHRlbmQgdG8gcmFyZWZ5SUQpLgptb2RzW1sxM11dIDwtIGxtZShmaXhlZCwgZGF0YSA9IHRyZW5kc1tpLF0sIHJhbmRvbSA9IGxpc3QodGF4YV9tb2QyID0gfiB0ZW1wdHJlbmRfYWJzLnNjLCBTVFVEWV9JRCA9IH4gdGVtcHRyZW5kX2Ficy5zYywgcmFyZWZ5SUQgPSB+MSkpICMgMzArIG1pbiB0byBmaXQKCm1vZHNbWzE0XV0gPC0gbG1lKGZpeGVkLCBkYXRhID0gdHJlbmRzW2ksXSwgcmFuZG9tID0gfjF8U1RVRFlfSUQsIHdlaWdodHMgPSB2YXJQb3dlcigtMC41LCB+bnlyQlQpKQptb2RzW1sxNV1dIDwtIGxtZShmaXhlZCwgZGF0YSA9IHRyZW5kc1tpLF0sIHJhbmRvbSA9IH4xfHRheGFfbW9kMiwgd2VpZ2h0cyA9IHZhclBvd2VyKC0wLjUsIH5ueXJCVCkpCm1vZHNbWzE2XV0gPC0gbG1lKGZpeGVkLCBkYXRhID0gdHJlbmRzW2ksXSwgcmFuZG9tID0gfjF8dGF4YV9tb2QyL1NUVURZX0lELCB3ZWlnaHRzID0gdmFyUG93ZXIoLTAuNSwgfm55ckJUKSkKbW9kc1tbMTddXSA8LSBsbWUoZml4ZWQsIGRhdGEgPSB0cmVuZHNbaSxdLCByYW5kb20gPSB+MXxTVFVEWV9JRC9yYXJlZnlJRCwgd2VpZ2h0cyA9IHZhclBvd2VyKC0wLjUsIH5ueXJCVCkpCm1vZHNbWzE4XV0gPC0gbG1lKGZpeGVkLCBkYXRhID0gdHJlbmRzW2ksXSwgcmFuZG9tID0gfjF8dGF4YV9tb2QyL1NUVURZX0lEL3JhcmVmeUlELCB3ZWlnaHRzID0gdmFyUG93ZXIoLTAuNSwgfm55ckJUKSkKbW9kc1tbMTldXSA8LSBsbWUoZml4ZWQsIGRhdGEgPSB0cmVuZHNbaSxdLCByYW5kb20gPSB+dGVtcHRyZW5kX2Ficy5zY3xTVFVEWV9JRCwgd2VpZ2h0cyA9IHZhclBvd2VyKC0wLjUsIH5ueXJCVCkpCm1vZHNbWzIwXV0gPC0gbG1lKGZpeGVkLCBkYXRhID0gdHJlbmRzW2ksXSwgcmFuZG9tID0gbGlzdChTVFVEWV9JRCA9IH4gdGVtcHRyZW5kX2Ficy5zYywgcmFyZWZ5SUQgPSB+MSksIHdlaWdodHMgPSB2YXJQb3dlcigtMC41LCB+bnlyQlQpKQptb2RzW1syMV1dIDwtIGxtZShmaXhlZCwgZGF0YSA9IHRyZW5kc1tpLF0sIHJhbmRvbSA9IGxpc3QodGF4YV9tb2QyID0gfiB0ZW1wdHJlbmRfYWJzLnNjLCBTVFVEWV9JRCA9IH4gMSksIHdlaWdodHMgPSB2YXJQb3dlcigtMC41LCB+bnlyQlQpKQptb2RzW1syMl1dIDwtIGxtZShmaXhlZCwgZGF0YSA9IHRyZW5kc1tpLF0sIHJhbmRvbSA9IGxpc3QodGF4YV9tb2QyID0gfiB0ZW1wdHJlbmRfYWJzLnNjLCBTVFVEWV9JRCA9IH4gMSwgcmFyZWZ5SUQgPSB+MSksIHdlaWdodHMgPSB2YXJQb3dlcigtMC41LCB+bnlyQlQpKQptb2RzW1syM11dIDwtIGxtZShmaXhlZCwgZGF0YSA9IHRyZW5kc1tpLF0sIHJhbmRvbSA9IGxpc3QodGF4YV9tb2QyID0gfiB0ZW1wdHJlbmRfYWJzLnNjLCBTVFVEWV9JRCA9IH4gdGVtcHRyZW5kX2Ficy5zYyksIHdlaWdodHMgPSB2YXJQb3dlcigtMC41LCB+bnlyQlQpKSAjIHNpbmd1bGFyIHByZWNpc2lvbiB3YXJuaW5nIHdpdGggbG1lQ29udHJvbChvcHQgPSAnb3B0aW0nKSBhbmQgY29udmVyZ2VuY2UgZXJyb3Igd2l0aG91dAptb2RzW1syNF1dIDwtIGxtZShmaXhlZCwgZGF0YSA9IHRyZW5kc1tpLF0sIHJhbmRvbSA9IGxpc3QodGF4YV9tb2QyID0gfiB0ZW1wdHJlbmRfYWJzLnNjLCBTVFVEWV9JRCA9IH4gdGVtcHRyZW5kX2Ficy5zYywgcmFyZWZ5SUQgPSB+MSksIHdlaWdodHMgPSB2YXJQb3dlcigtMC41LCB+bnlyQlQpKSAjIHNpbmd1bGFyIHByZWNpc2lvbiB3YXJuaW5nIHdpdGggbG1lQ29udHJvbChvcHQgPSAnb3B0aW0nKSBhbmQgY29udmVyZ2VuY2UgZXJyb3Igd2l0aG91dAoKbW9kc1tbMjVdXSA8LSBsbWUoZml4ZWQsIGRhdGEgPSB0cmVuZHNbaSxdLCByYW5kb20gPSB+MXx0YXhhX21vZDIsIHdlaWdodHMgPSB2YXJQb3dlcigtMC41LCB+YWJzKHRlbXB0cmVuZCkpKQptb2RzW1syNl1dIDwtIGxtZShmaXhlZCwgZGF0YSA9IHRyZW5kc1tpLF0sIHJhbmRvbSA9IH4xfFNUVURZX0lELCB3ZWlnaHRzID0gdmFyUG93ZXIoLTAuNSwgfmFicyh0ZW1wdHJlbmQpKSkKbW9kc1tbMjddXSA8LSBsbWUoZml4ZWQsIGRhdGEgPSB0cmVuZHNbaSxdLCByYW5kb20gPSB+MXxTVFVEWV9JRC9yYXJlZnlJRCwgd2VpZ2h0cyA9IHZhclBvd2VyKC0wLjUsIH5hYnModGVtcHRyZW5kKSkpCm1vZHNbWzI4XV0gPC0gbG1lKGZpeGVkLCBkYXRhID0gdHJlbmRzW2ksXSwgcmFuZG9tID0gfjF8dGF4YV9tb2QyL1NUVURZX0lEL3JhcmVmeUlELCB3ZWlnaHRzID0gdmFyUG93ZXIoLTAuNSwgfmFicyh0ZW1wdHJlbmQpKSkKbW9kc1tbMjldXSA8LSBsbWUoZml4ZWQsIGRhdGEgPSB0cmVuZHNbaSxdLCByYW5kb20gPSB+dGVtcHRyZW5kX2Ficy5zY3xTVFVEWV9JRCwgd2VpZ2h0cyA9IHZhclBvd2VyKC0wLjUsIH5hYnModGVtcHRyZW5kKSkpCm1vZHNbWzMwXV0gPC0gbG1lKGZpeGVkLCBkYXRhID0gdHJlbmRzW2ksXSwgcmFuZG9tID0gfnRlbXB0cmVuZF9hYnMuc2N8dGF4YV9tb2QyL1NUVURZX0lELCB3ZWlnaHRzID0gdmFyUG93ZXIoLTAuNSwgfmFicyh0ZW1wdHJlbmQpKSwgY29udHJvbCA9IGxtZUNvbnRyb2wob3B0ID0gIm9wdGltIikpCm1vZHNbWzMxXV0gPC0gbG1lKGZpeGVkLCBkYXRhID0gdHJlbmRzW2ksXSwgcmFuZG9tID0gbGlzdChTVFVEWV9JRCA9IH4gdGVtcHRyZW5kX2Ficy5zYywgcmFyZWZ5SUQgPSB+MSksIHdlaWdodHMgPSB2YXJQb3dlcigtMC41LCB+YWJzKHRlbXB0cmVuZCkpKQptb2RzW1szMl1dIDwtIGxtZShmaXhlZCwgZGF0YSA9IHRyZW5kc1tpLF0sIHJhbmRvbSA9IGxpc3QodGF4YV9tb2QyID0gfiB0ZW1wdHJlbmRfYWJzLnNjLCBTVFVEWV9JRCA9IH4gdGVtcHRyZW5kX2Ficy5zYywgcmFyZWZ5SUQgPSB+MSksIHdlaWdodHMgPSB2YXJQb3dlcigtMC41LCB+YWJzKHRlbXB0cmVuZCkpLCBjb250cm9sID0gbG1lQ29udHJvbChvcHQgPSAib3B0aW0iKSkgIyBzaW5ndWxhciBwcmVjaXNpb24gd2FybmluZwoKYWljcyA8LSBzYXBwbHkobW9kcywgQUlDKQptaW5haWNzIDwtIGFpY3MgLSBtaW4oYWljcykKbWluYWljcwp3aGljaC5taW4oYWljcykKYGBgCkNob29zZXMgdGhlIHJhbmRvbSBzbG9wZXMgKHRlbXB0cmVuZF9hYnMpICYgaW50ZXJjZXB0cyBmb3IgU1RVRFlfSUQsIG92ZXJkaXNwZXJzaW9uLCBhbmQgdmFyaWFuY2Ugc2NhbGVkIHRvIG51bWJlciBvZiB5ZWFycy4KV2UgaGF2ZW4ndCBkZWFsdCB3aXRoIHBvdGVudGlhbCB0ZXN0aW5nIG9uIHRoZSBib3VuZGFyeSBpc3N1ZXMgaGVyZSB5ZXQuCgojIFJlc3VsdHMKIyMgV2hlcmUgZG8gd2UgaGF2ZSBkYXRhPwpgYGB7ciBtYXB9CndvcmxkIDwtIG1hcF9kYXRhKCd3b3JsZCcpCmdncGxvdCh3b3JsZCwgYWVzKHggPSBsb25nLCB5ID0gbGF0LCBncm91cCA9IGdyb3VwKSkgKwogICAgZ2VvbV9wb2x5Z29uKGZpbGwgPSAnbGlnaHRncmF5JywgY29sb3IgPSAnd2hpdGUnKSArCiAgICBnZW9tX3BvaW50KGRhdGEgPSB0cmVuZHMsIGFlcyhyYXJlZnlJRF94LCByYXJlZnlJRF95LCBncm91cCA9IFJFQUxNLCBjb2xvciA9IFJFQUxNKSwgc2l6ZSA9IDAuNSwgYWxwaGEgPSAwLjQpICArCiAgICBzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZT0iU2V0MSIsIG5hbWUgPSAnUmVhbG0nKSArCiAgdGhlbWUocGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfYmxhbmsoKSwgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLCBheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gImJsYWNrIiksCiAgICAgICAgbGVnZW5kLmtleT1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0PWVsZW1lbnRfdGV4dChzaXplPTE2KSwKICAgICAgICBheGlzLnRpdGxlPWVsZW1lbnRfdGV4dChzaXplPTIwKSkgKwogIGxhYnMoeCA9ICdMb25naXR1ZGUgKMKwKScsIHkgPSAnTGF0aXR1ZGUgKMKwKScpCmBgYAoKTW9zdGx5IG5vcnRoZXJuIGhlbWlzcGhlcmUsIGJ1dCBzcHJlYWQgYWxsIG92ZXIuIE5vIHNvIG11Y2ggaW4gQWZyaWNhIG9yIG11Y2ggb2YgQXNpYS4KCgojIyBQbG90IHR1cm5vdmVyIHZzLiBleHBsYW5hdG9yeSB2YXJpYWJsZXMKTGluZXMgYXJlIGdncGxvdCBzbW9vdGhlciBmaXRzIGJ5IHJlYWxtLgpgYGB7ciBwbG90IHR1cm5vdmVyIHYgdGVtcCB0cmVuZCwgZWNobz1GQUxTRSwgZmlnLmhlaWdodCA9IDE2LCBmaWcud2lkdGggPSA5LH0KCnAxIDwtIGdncGxvdCh0cmVuZHMsIGFlcyhSRUFMTSwgSnR1dHJlbmQpKSArCiAgZ2VvbV9ib3hwbG90KG5hLnJtID0gVFJVRSkgKyAKICBsYWJzKHggPSAnUmVhbG0nLCB5ID0gJ0phY2NhcmQgdHVybm92ZXIgdGVtcG9yYWwgdHJlbmQnKQoKcDIgPC0gZ2dwbG90KHRyZW5kcywgYWVzKHRlbXBhdmUsIEp0dXRyZW5kLCBzaXplID0gbnlyQlQpKSArCiAgZ2VvbV9wb2ludChhZXMoY29sb3IgPSBSRUFMTSksIHNpemUgPSAwLjIsIGFscGhhID0gMC41LCBuYS5ybSA9IFRSVUUpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gJ2dhbScsIGZvcm11bGEgPSB5IH4gcyh4LCBicyA9ICJjcyIpLCBuYS5ybSA9IFRSVUUsIGNvbG9yID0gJ2JsYWNrJykgKwogIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlPSJTZXQxIikgKyAKICBsYWJzKHggPSAnVGVtcGVyYXR1cmUgKMKwQyknLCB5ID0gJ0phY2NhcmQgdHVybm92ZXIgdGVtcG9yYWwgdHJlbmQnKQoKcDMgPC0gZ2dwbG90KHRyZW5kcywgYWVzKHRlbXBhdmVfbWV0YWIsIEp0dXRyZW5kLCBzaXplID0gbnlyQlQpKSArCiAgZ2VvbV9wb2ludChhZXMoY29sb3IgPSBSRUFMTSksIHNpemUgPSAwLjIsIGFscGhhID0gMC41LCBuYS5ybSA9IFRSVUUpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gJ2dhbScsIGZvcm11bGEgPSB5IH4gcyh4LCBicyA9ICJjcyIpLCBuYS5ybSA9IFRSVUUsIGNvbG9yID0gJ2JsYWNrJykgKwogIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlPSJTZXQxIikgKyAKICBsYWJzKHggPSAnTWV0YWJvbGljIHRlbXBlcmF0dXJlICjCsEMpJywgeSA9ICdKYWNjYXJkIHR1cm5vdmVyIHRlbXBvcmFsIHRyZW5kJykKCnA0IDwtIGdncGxvdCh0cmVuZHMsIGFlcyhzZWFzLCBKdHV0cmVuZCwgc2l6ZSA9IG55ckJUKSkgKwogIGdlb21fcG9pbnQoYWVzKGNvbG9yID0gUkVBTE0pLCBzaXplID0gMC4yLCBhbHBoYSA9IDAuNSwgbmEucm0gPSBUUlVFKSArIAogIGdlb21fc21vb3RoKG1ldGhvZCA9ICdnYW0nLCBmb3JtdWxhID0geSB+IHMoeCwgYnMgPSAiY3MiKSwgbmEucm0gPSBUUlVFLCBjb2xvciA9ICdibGFjaycpICsKICBzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZT0iU2V0MSIpICsgCiAgbGFicyh4ID0gJ1NlYXNvbmFsaXR5ICjCsEMpJywgeSA9ICdKYWNjYXJkIHR1cm5vdmVyIHRlbXBvcmFsIHRyZW5kJykKCnA1IDwtIGdncGxvdCh0cmVuZHMsIGFlcyhtaWNyb2NsaW0sIEp0dXRyZW5kLCBzaXplID0gbnlyQlQpKSArCiAgZ2VvbV9wb2ludChhZXMoY29sb3IgPSBSRUFMTSksIHNpemUgPSAwLjIsIGFscGhhID0gMC41LCBuYS5ybSA9IFRSVUUpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gJ2dhbScsIGZvcm11bGEgPSB5IH4gcyh4LCBicyA9ICJjcyIpLCBuYS5ybSA9IFRSVUUsIGNvbG9yID0gJ2JsYWNrJykgKwogIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlPSJTZXQxIikgKyAKICBzY2FsZV94X2xvZzEwKCkgKwogIGxhYnMoeCA9ICdNaWNyb2NsaW1hdGUgYXZhaWxhYmlsaXR5ICjCsEMpJywgeSA9ICdKYWNjYXJkIHR1cm5vdmVyIHRlbXBvcmFsIHRyZW5kJykKCnA2IDwtIGdncGxvdCh0cmVuZHMsIGFlcyhtYXNzX21lYW5fd2VpZ2h0LCBKdHV0cmVuZCwgc2l6ZSA9IG55ckJUKSkgKwogIGdlb21fcG9pbnQoYWVzKGNvbG9yID0gUkVBTE0pLCBzaXplID0gMC4yLCBhbHBoYSA9IDAuNSwgbmEucm0gPSBUUlVFKSArIAogIGdlb21fc21vb3RoKG1ldGhvZCA9ICdnYW0nLCBmb3JtdWxhID0geSB+IHMoeCwgYnMgPSAiY3MiKSwgbmEucm0gPSBUUlVFLCBjb2xvciA9ICdibGFjaycpICsKICBzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZT0iU2V0MSIpICsgCiAgc2NhbGVfeF9sb2cxMCgpICsKICBsYWJzKHggPSAnTWFzcyAoZykpJywgeSA9ICdKYWNjYXJkIHR1cm5vdmVyIHRlbXBvcmFsIHRyZW5kJykKCnA3IDwtIGdncGxvdCh0cmVuZHMsIGFlcyhzcGVlZF9tZWFuX3dlaWdodCsxLCBKdHV0cmVuZCwgc2l6ZSA9IG55ckJUKSkgKwogIGdlb21fcG9pbnQoYWVzKGNvbG9yID0gUkVBTE0pLCBzaXplID0gMC4yLCBhbHBoYSA9IDAuNSwgbmEucm0gPSBUUlVFKSArIAogIGdlb21fc21vb3RoKG1ldGhvZCA9ICdnYW0nLCBmb3JtdWxhID0geSB+IHMoeCwgYnMgPSAiY3MiKSwgbmEucm0gPSBUUlVFLCBjb2xvciA9ICdibGFjaycpICsKICBzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZT0iU2V0MSIpICsgCiAgc2NhbGVfeF9sb2cxMCgpICsKICBsYWJzKHggPSAnU3BlZWQgKGttIC8gaHIpKScsIHkgPSAnSmFjY2FyZCB0dXJub3ZlciB0ZW1wb3JhbCB0cmVuZCcpCgpwOCA8LSBnZ3Bsb3QodHJlbmRzLCBhZXMobGlmZXNwYW5fbWVhbl93ZWlnaHQsIEp0dXRyZW5kLCBzaXplID0gbnlyQlQpKSArCiAgZ2VvbV9wb2ludChhZXMoY29sb3IgPSBSRUFMTSksIHNpemUgPSAwLjIsIGFscGhhID0gMC41LCBuYS5ybSA9IFRSVUUpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gJ2dhbScsIGZvcm11bGEgPSB5IH4gcyh4LCBicyA9ICJjcyIpLCBuYS5ybSA9IFRSVUUsIGNvbG9yID0gJ2JsYWNrJykgKwogIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlPSJTZXQxIikgKyAKICBzY2FsZV94X2xvZzEwKCkgKwogIGxhYnMoeCA9ICdMaWZlc3BhbiAoeXIpKScsIHkgPSAnSmFjY2FyZCB0dXJub3ZlciB0ZW1wb3JhbCB0cmVuZCcpCgpwOSA8LSBnZ3Bsb3QodHJlbmRzLCBhZXMoY29uc2ZyYWMsIEp0dXRyZW5kLCBzaXplID0gbnlyQlQpKSArCiAgZ2VvbV9wb2ludChhZXMoY29sb3IgPSBSRUFMTSksIHNpemUgPSAwLjIsIGFscGhhID0gMC41LCBuYS5ybSA9IFRSVUUpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gJ2dhbScsIGZvcm11bGEgPSB5IH4gcyh4LCBicyA9ICJjcyIsIGsgPSAzKSwgbmEucm0gPSBUUlVFLCBjb2xvciA9ICdibGFjaycpICsKICBzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZT0iU2V0MSIpICsgCiAgbGFicyh4ID0gJ0ZyYWN0aW9uIGNvbnN1bWVycycsIHkgPSAnSmFjY2FyZCB0dXJub3ZlciB0ZW1wb3JhbCB0cmVuZCcpCgpwMTAgPC0gZ2dwbG90KHRyZW5kcywgYWVzKGVuZG9mcmFjLCBKdHV0cmVuZCwgc2l6ZSA9IG55ckJUKSkgKwogIGdlb21fcG9pbnQoYWVzKGNvbG9yID0gUkVBTE0pLCBzaXplID0gMC4yLCBhbHBoYSA9IDAuNSwgbmEucm0gPSBUUlVFKSArIAogIGdlb21fc21vb3RoKG1ldGhvZCA9ICdnYW0nLCBmb3JtdWxhID0geSB+IHMoeCwgYnMgPSAiY3MiLCBrID0gMyksIG5hLnJtID0gVFJVRSwgY29sb3IgPSAnYmxhY2snKSArCiAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGU9IlNldDEiKSArIAogIGxhYnMoeCA9ICdGcmFjdGlvbiBlbmRvdGhlcm1zJywgeSA9ICdKYWNjYXJkIHR1cm5vdmVyIHRlbXBvcmFsIHRyZW5kJykKCnAxMSA8LSBnZ3Bsb3QodHJlbmRzLCBhZXMoTnNwcCwgSnR1dHJlbmQsIHNpemUgPSBueXJCVCkpICsKICBnZW9tX3BvaW50KGFlcyhjb2xvciA9IFJFQUxNKSwgc2l6ZSA9IDAuMiwgYWxwaGEgPSAwLjUsIG5hLnJtID0gVFJVRSkgKyAKICBnZW9tX3Ntb290aChtZXRob2QgPSAnZ2FtJywgZm9ybXVsYSA9IHkgfiBzKHgsIGJzID0gImNzIiksIG5hLnJtID0gVFJVRSwgY29sb3IgPSAnYmxhY2snKSArCiAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGU9IlNldDEiKSArIAogIHNjYWxlX3hfbG9nMTAoKSArCiAgbGFicyh4ID0gJ051bWJlciBvZiBzcGVjaWVzJywgeSA9ICdKYWNjYXJkIHR1cm5vdmVyIHRlbXBvcmFsIHRyZW5kJykKCnAxMiA8LSBnZ3Bsb3QodHJlbmRzLCBhZXModGhlcm1hbF9iaWFzLCBKdHV0cmVuZCwgc2l6ZSA9IG55ckJUKSkgKwogIGdlb21fcG9pbnQoYWVzKGNvbG9yID0gUkVBTE0pLCBzaXplID0gMC4yLCBhbHBoYSA9IDAuNSwgbmEucm0gPSBUUlVFKSArIAogIGdlb21fc21vb3RoKG1ldGhvZCA9ICdnYW0nLCBmb3JtdWxhID0geSB+IHMoeCwgYnMgPSAiY3MiKSwgbmEucm0gPSBUUlVFLCBjb2xvciA9ICdibGFjaycpICsKICBzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZT0iU2V0MSIpICsgCiAgbGFicyh4ID0gJ1RoZXJtYWwgYmlhcyAowrBDKScsIHkgPSAnSmFjY2FyZCB0dXJub3ZlciB0ZW1wb3JhbCB0cmVuZCcpCgpwMTMgPC0gZ2dwbG90KHRyZW5kcywgYWVzKG5wcCwgSnR1dHJlbmQsIHNpemUgPSBueXJCVCkpICsKICBnZW9tX3BvaW50KGFlcyhjb2xvciA9IFJFQUxNKSwgc2l6ZSA9IDAuMiwgYWxwaGEgPSAwLjUsIG5hLnJtID0gVFJVRSkgKyAKICBnZW9tX3Ntb290aChtZXRob2QgPSAnZ2FtJywgZm9ybXVsYSA9IHkgfiBzKHgsIGJzID0gImNzIiksIG5hLnJtID0gVFJVRSwgY29sb3IgPSAnYmxhY2snKSArCiAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGU9IlNldDEiKSArIAogIHNjYWxlX3hfbG9nMTAoKSArCiAgbGFicyh4ID0gJ05ldCBwcmltYXJ5IHByb2R1Y3Rpdml0eSAobWcgQyAvIG0yIC8gZGF5KScsIHkgPSAnSmFjY2FyZCB0dXJub3ZlciB0ZW1wb3JhbCB0cmVuZCcpCgpwMTQgPC0gZ2dwbG90KHRyZW5kcywgYWVzKGh1bWFuLCBKdHV0cmVuZCwgY29sb3IgPSBSRUFMTSwgc2l6ZSA9IG55ckJUKSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDAuMiwgYWxwaGEgPSAwLjUsIG5hLnJtID0gVFJVRSkgKyAKICBnZW9tX3Ntb290aChtZXRob2QgPSAnZ2FtJywgZm9ybXVsYSA9IHkgfiBzKHgsIGJzID0gImNzIiwgayA9IDUpLCBuYS5ybSA9IFRSVUUpICsKICBzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZT0iU2V0MSIpICsgCiAgbGFicyh4ID0gJ0Jvd2xlciBodW1hbiBpbXBhY3Qgc2NvcmUnLCB5ID0gJ0phY2NhcmQgdHVybm92ZXIgdGVtcG9yYWwgdHJlbmQnKQoKcDE1IDwtIGdncGxvdCh0cmVuZHMsIGFlcyh0ZW1wdHJlbmQsIEp0dXRyZW5kLCBjb2xvciA9IFJFQUxNLCBzaXplID0gbnlyQlQpKSArCiAgZ2VvbV9wb2ludChzaXplID0gMC4yLCBhbHBoYSA9IDAuNSwgbmEucm0gPSBUUlVFKSArIAogIGdlb21fc21vb3RoKG1ldGhvZCA9ICdnYW0nLCBmb3JtdWxhID0geSB+IHMoeCwgYnMgPSAiY3MiKSwgbmEucm0gPSBUUlVFKSArCiAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGU9IlNldDEiKSArIAogIGxhYnMoeCA9ICdUZW1wZXJhdHVyZSB0cmVuZCAowrBDL3lyKScsIHkgPSAnSmFjY2FyZCB0dXJub3ZlciB0ZW1wb3JhbCB0cmVuZCcpCgojIEphY2NhcmQgdG90YWwgdHJlbmQgdnMuIHRlbXBlcmF0dXJlIHRyZW5kIChhY3Jvc3MgYWxsIHllYXJzKQpwMTYgPC0gZ2dwbG90KHRyZW5kcywgYWVzKHRlbXB0cmVuZCwgSmJldGF0cmVuZCwgY29sb3IgPSBSRUFMTSwgc2l6ZSA9IG55ckJUKSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDAuMiwgYWxwaGEgPSAwLjUsIG5hLnJtID0gVFJVRSkgKyAKICBnZW9tX3Ntb290aChtZXRob2QgPSAnZ2FtJywgZm9ybXVsYSA9IHkgfiBzKHgsIGJzID0gImNzIiksIG5hLnJtID0gVFJVRSkgKwogIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlPSJTZXQxIikgKyAKICBsYWJzKHggPSAnVGVtcGVyYXR1cmUgdHJlbmQgKMKwQy95ZWFyKScsIHkgPSAnSmFjY2FyZCB0b3RhbCB0ZW1wb3JhbCB0cmVuZCcpCgoKIyBIb3JuLU1vcmlzaXRhIHR1cm5vdmVyIHRyZW5kIHZzLiB0ZW1wZXJhdHVyZSB0cmVuZCAoYWNyb3NzIGFsbCB5ZWFycykKcDE3IDwtIGdncGxvdCh0cmVuZHMsIGFlcyh0ZW1wdHJlbmQsIEhvcm50cmVuZCwgY29sb3IgPSBSRUFMTSwgc2l6ZSA9IG55ckJUKSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDAuMiwgYWxwaGEgPSAwLjUsIG5hLnJtID0gVFJVRSkgKyAKICBnZW9tX3Ntb290aChtZXRob2QgPSAnZ2FtJywgZm9ybXVsYSA9IHkgfiBzKHgsIGJzID0gImNzIiksIG5hLnJtID0gVFJVRSkgKwogIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlPSJTZXQxIikgKyAKICBsYWJzKHggPSAnVGVtcGVyYXR1cmUgdHJlbmQgKMKwQy95ZWFyKScsIHkgPSAnTW9yaXNpdGEtSG9ybiB0ZW1wb3JhbCB0dXJub3ZlcicpCgoKZ3JpZC5hcnJhbmdlKHAxLCBwMiwgcDMsIHA0LCBwNSwgcDYsIHA3LCBwOCwgcDksIHAxMCwgcDExLCBwMTIsIHAxMywgcDE0LCBwMTUsIHAxNiwgcDE3LCBuY29sID0gMikKYGBgCgpTdHJvbmcgdHJlbmRzIHdpdGggdGVtcGVyYXR1cmUgY2hhbmdlLCBidXQgdHJlbmRzIGFyZSBwcmV0dHkgc3ltbWV0cmljIGFyb3VuZCBubyB0cmVuZCBpbiB0ZW1wZXJhdHVyZSwgd2hpY2ggaW1wbGllcyB3YXJtaW5nIG9yIGNvb2xpbmcgZHJpdmVzIHNpbWlsYXIgZGVncmVlIG9mIGNvbW11bml0eSB0dXJub3Zlci4KU29tZSBpbmRpY2F0aW9uIG9mIGxlc3MgdHVybm92ZXIgZm9yIGxhcmdlciBvcmdhbmlzbXMgKG1hc3MpCkhpZ2hlciB0dXJub3ZlciBvbiBsYW5kIHdpdGggaGlnaGVyIHNlYXNvbmFsaXR5PwpNb3JlIHR1cm5vdmVyIGZvciBzaG9ydGVyLWxpdmVkIG9yZ2FuaXNtcz8KTm8gcmVhbGx5IGNsZWFyIGRpZmZlcmVuY2VzIGFtb25nIHJlYWxtcy4KCgpBdmVyYWdlIHJhdGVzIG9mIHR1cm5vdmVyCmBgYHtyIHJhdGVzIG9mIHR1cm5vdmVyfQp0cmVuZHNbYWJzKHRlbXB0cmVuZCkgPj0gMC41LCAuKG1lYW4oSnR1dHJlbmQpLCBzZChKdHV0cmVuZCkvc3FydCguTikpXSAjIHR1cm5vdmVyIHBlciB5ZWFyIGZvciBsb2NhdGlvbnMgY2hhbmdpbmcgdGVtcGVyYXR1cmUKdHJlbmRzW2Ficyh0ZW1wdHJlbmQpIDwgMC4xLCAuKG1lYW4oSnR1dHJlbmQpLCBzZChKdHV0cmVuZCkvc3FydCguTikpXSAjIG5vdCBjaGFuZ2luZyB0ZW1wZXJhdHVyZQp0cmVuZHNbdGVtcHRyZW5kID49IDAuNSwgLihtZWFuKEp0dXRyZW5kKSwgc2QoSnR1dHJlbmQpL3NxcnQoLk4pKV0gIyB3YXJtaW5nCnRyZW5kc1t0ZW1wdHJlbmQgPD0gLTAuNSwgLihtZWFuKEp0dXRyZW5kKSwgc2QoSnR1dHJlbmQpL3NxcnQoLk4pKV0gIyBjb29saW5nCgp0cmVuZHNbYWJzKHRlbXB0cmVuZCkgPj0gMC41ICYgYWJzKHJhcmVmeUlEX3kpIDwgMzUsIC4obWVhbihKdHV0cmVuZCksIHNkKEp0dXRyZW5kKS9zcXJ0KC5OKSldICMgdHJvcGljcyBhbmQgc3ViLXRyb3BpY3MKdHJlbmRzW2Ficyh0ZW1wdHJlbmQpID49IDAuNSAmIGFicyhyYXJlZnlJRF95KSA+PSAzNSAmIGFicyhyYXJlZnlJRF95KSA8IDY2LjU2MzM5LCAuKG1lYW4oSnR1dHJlbmQpLCBzZChKdHV0cmVuZCkvc3FydCguTikpXSAjIHRlbXBlcmF0ZQp0cmVuZHNbYWJzKHRlbXB0cmVuZCkgPj0gMC41ICYgYWJzKHJhcmVmeUlEX3kpID49IDY2LjU2MzM5LCAuKG1lYW4oSnR1dHJlbmQpLCBzZChKdHV0cmVuZCkvc3FydCguTikpXSAjIGFyY3RpYwpgYGAKCgoKIyMgQ29tcGFyZSBjb3ZhcmlhdGVzIGFjcm9zcyByZWFsbXMKYGBge3IgY29tcGFyZSBhY3Jvc3MgcmVhbG1zLCBmaWcuaGVpZ2h0PTEyLCBmaWcud2lkdGg9OX0KaSA8LSB0cmVuZHNbLCAhZHVwbGljYXRlZChyYXJlZnlJRCldOyBzdW0oaSkKcGFyKG1mcm93PWMoNSwzKSkKYmVhbnBsb3QocmFyZWZ5SURfeSB+IFJFQUxNLCBkYXRhID0gdHJlbmRzW2ksXSwgd2hhdCA9IGMoMSwxLDEsMSksIGNvbCA9IGMoIiNDQUIyRDYiLCAiIzMzQTAyQyIsICIjQjJERjhBIiksIGJvcmRlciA9ICIjQ0FCMkQ2IiwgeWxhYiA9ICdMYXRpdHVkZSAoZGVnTiknLCBsbCA9IDAuMDUpCmJlYW5wbG90KHRlbXBhdmUgfiBSRUFMTSwgZGF0YSA9IHRyZW5kc1tpLF0sIHdoYXQgPSBjKDEsMSwxLDEpLCBjb2wgPSBjKCIjQ0FCMkQ2IiwgIiMzM0EwMkMiLCAiI0IyREY4QSIpLCBib3JkZXIgPSAiI0NBQjJENiIsIHlsYWIgPSAnVGVtcGVyYXR1cmUgKGRlZ0MpJywgbGwgPSAwLjA1KQpiZWFucGxvdCh0ZW1wYXZlX21ldGFiIH4gUkVBTE0sIGRhdGEgPSB0cmVuZHNbaSxdLCB3aGF0ID0gYygxLDEsMSwxKSwgY29sID0gYygiI0NBQjJENiIsICIjMzNBMDJDIiwgIiNCMkRGOEEiKSwgYm9yZGVyID0gIiNDQUIyRDYiLCB5bGFiID0gJ01ldGFib2xpYyBUZW1wZXJhdHVyZSAoZGVnQyknLCBsbCA9IDAuMDUsIGJ3ID0gJ25yZDAnKSAjIG5yZDAgYmFuZHdpZHRoIHRvIGNhbGN1bGF0aW9uIGdhcApiZWFucGxvdChzZWFzIH4gUkVBTE0sIGRhdGEgPSB0cmVuZHNbaSxdLCB3aGF0ID0gYygxLDEsMSwxKSwgY29sID0gYygiI0NBQjJENiIsICIjMzNBMDJDIiwgIiNCMkRGOEEiKSwgYm9yZGVyID0gIiNDQUIyRDYiLCB5bGFiID0gJ1NlYXNvbmFsaXR5IChkZWdDKScsIGxsID0gMC4wNSkKYmVhbnBsb3QobWljcm9jbGltIH4gUkVBTE0sIGRhdGEgPSB0cmVuZHNbaSxdLCB3aGF0ID0gYygxLDEsMSwxKSwgY29sID0gYygiI0NBQjJENiIsICIjMzNBMDJDIiwgIiNCMkRGOEEiKSwgYm9yZGVyID0gIiNDQUIyRDYiLCB5bGFiID0gJ01pY3JvY2xpbWF0ZXMgKGRlZ0MpJywgbGwgPSAwLjA1KQpiZWFucGxvdCh0ZW1wdHJlbmQgfiBSRUFMTSwgZGF0YSA9IHRyZW5kc1tpLF0sIHdoYXQgPSBjKDEsMSwxLDEpLCBjb2wgPSBjKCIjQ0FCMkQ2IiwgIiMzM0EwMkMiLCAiI0IyREY4QSIpLCBib3JkZXIgPSAiI0NBQjJENiIsIHlsYWIgPSAnVGVtcGVyYXR1cmUgdHJlbmQgKGRlZ0MveXIpJywgbGwgPSAwLjA1KQpiZWFucGxvdChtYXNzX21lYW5fd2VpZ2h0IH4gUkVBTE0sIGRhdGEgPSB0cmVuZHNbaSxdLCB3aGF0ID0gYygxLDEsMSwxKSwgY29sID0gYygiI0NBQjJENiIsICIjMzNBMDJDIiwgIiNCMkRGOEEiKSwgYm9yZGVyID0gIiNDQUIyRDYiLCB5bGFiID0gJ01hc3MgKGcpJywgbGwgPSAwLjA1LCBsb2cgPSAneScpCmJlYW5wbG90KHNwZWVkX21lYW5fd2VpZ2h0ICsxIH4gUkVBTE0sIGRhdGEgPSB0cmVuZHNbaSxdLCB3aGF0ID0gYygxLDEsMSwxKSwgY29sID0gYygiI0NBQjJENiIsICIjMzNBMDJDIiwgIiNCMkRGOEEiKSwgYm9yZGVyID0gIiNDQUIyRDYiLCB5bGFiID0gJ1NwZWVkIChrbS9ociknLCBsbCA9IDAuMDUsIGxvZyA9ICd5JykKYmVhbnBsb3QobGlmZXNwYW5fbWVhbl93ZWlnaHQgfiBSRUFMTSwgZGF0YSA9IHRyZW5kc1tpLF0sIHdoYXQgPSBjKDEsMSwxLDEpLCBjb2wgPSBjKCIjQ0FCMkQ2IiwgIiMzM0EwMkMiLCAiI0IyREY4QSIpLCBib3JkZXIgPSAiI0NBQjJENiIsIHlsYWIgPSAnTGlmZXNwYW4gKHlyKScsIGxsID0gMC4wNSwgbG9nID0gJ3knKQojYmVhbnBsb3QoY29uc2ZyYWMgfiBSRUFMTSwgZGF0YSA9IHRyZW5kc1tpLF0sIHdoYXQgPSBjKDEsMSwxLDEpLCBjb2wgPSBjKCIjQ0FCMkQ2IiwgIiMzM0EwMkMiLCAiI0IyREY4QSIpLCBib3JkZXIgPSAiI0NBQjJENiIsIHlsYWIgPSAnQ29uc3VtZXJzIChmcmFjdGlvbiknLCBsbCA9IDAuMDUsIGxvZyA9ICcnKSAjIHRvbyBzcGFyc2UKI2JlYW5wbG90KGVuZG9mcmFjIH4gUkVBTE0sIGRhdGEgPSB0cmVuZHNbaSxdLCB3aGF0ID0gYygxLDEsMSwxKSwgY29sID0gYygiI0NBQjJENiIsICIjMzNBMDJDIiwgIiNCMkRGOEEiKSwgYm9yZGVyID0gIiNDQUIyRDYiLCB5bGFiID0gJ0VuZG90aGVybXMgKGZyYWN0aW9uKScsIGxsID0gMC4wNSwgbG9nID0gJycpICMgdG9vIHNwYXJzZQpiZWFucGxvdChOc3BwIH4gUkVBTE0sIGRhdGEgPSB0cmVuZHNbaSxdLCB3aGF0ID0gYygxLDEsMSwxKSwgY29sID0gYygiI0NBQjJENiIsICIjMzNBMDJDIiwgIiNCMkRGOEEiKSwgYm9yZGVyID0gIiNDQUIyRDYiLCB5bGFiID0gJ051bWJlciBvZiBzcGVjaWVzJywgbGwgPSAwLjA1LCBsb2cgPSAneScpCmJlYW5wbG90KHRoZXJtYWxfYmlhcyB+IFJFQUxNLCBkYXRhID0gdHJlbmRzW2kgJiAhaXMubmEodGhlcm1hbF9iaWFzKSxdLCB3aGF0ID0gYygxLDEsMSwxKSwgY29sID0gYygiI0NBQjJENiIsICIjMzNBMDJDIiwgIiNCMkRGOEEiKSwgYm9yZGVyID0gIiNDQUIyRDYiLCB5bGFiID0gJ1RoZXJtYWwgYmlhcyAoZGVnQyknLCBsbCA9IDAuMDUpCmJlYW5wbG90KG5wcCB+IFJFQUxNLCBkYXRhID0gdHJlbmRzW2ksXSwgd2hhdCA9IGMoMSwxLDEsMSksIGNvbCA9IGMoIiNDQUIyRDYiLCAiIzMzQTAyQyIsICIjQjJERjhBIiksIGJvcmRlciA9ICIjQ0FCMkQ2IiwgeWxhYiA9ICdOUFAnLCBsbCA9IDAuMDUpCmJlYW5wbG90KGh1bWFuIH4gUkVBTE0sIGRhdGEgPSB0cmVuZHNbaSxdLCB3aGF0ID0gYygxLDEsMSwxKSwgY29sID0gYygiI0NBQjJENiIsICIjMzNBMDJDIiwgIiNCMkRGOEEiKSwgYm9yZGVyID0gIiNDQUIyRDYiLCB5bGFiID0gJ0h1bWFuIGltcGFjdCBzY29yZScsIGxsID0gMC4wNSkKCmBgYAoKTWFyaW5lIGFyZSBpbiBnZW5lcmFsbHkgd2FybWVyIGxvY2F0aW9ucyAoc2Vhd2F0ZXIgZG9lc24ndCBmcmVlemUpCk1hcmluZSBoYXZlIG11Y2ggbG93ZXIgc2Vhc29uYWxpdHkuCk1hcmluZSBhbmQgZnJlc2h3YXRlciBoYXZlIHNvbWUgdmVyeSBzbWFsbCBtYXNzZXMgKHBsYW5rdG9uKSwgYnV0IG11Y2ggb2YgZGF0YXNldCBpcyBzaW1pbGFyIHRvIHRlcnJlc3RyaWFsLgpNYXJpbmUgaGFzIGEgbG90IG9mIHNsb3csIGNyYXdsaW5nIG9yZ2FuaXNtcywgYnV0IGxhbmQgaGFzIHBsYW50cy4gTGFuZCBhbHNvIGhhcyBiaXJkcyAoZmFzdCkuCgoKCgojIyBUZW1wZXJhdHVyZS1vbmx5IG1vZGVsIChKdHV0cmVuZCwgSmJldGF0cmVuZCwgSG9ybnRyZW5kKQpgYGB7ciBMTUUgSmFjYXJkIHR1cm5vdmVyIHRlbXBlcmF0dXJlIG9ubHl9CmkgPC0gdHJlbmRzWywgY29tcGxldGUuY2FzZXMoSnR1dHJlbmQsIFJFQUxNLCB0ZW1wdHJlbmQpXQoKcmFuZGVmIDwtIGxpc3QoU1RVRFlfSUQgPSB+IGFicyh0ZW1wdHJlbmQpLCByYXJlZnlJRCA9IH4xKQp2YXJlZiA8LSB2YXJQb3dlcigtMC41LCB+bnlyQlQpCgppZihmaWxlLmV4aXN0cygndGVtcC9tb2Rvbmx5VHRyZW5kLnJkcycpKXsKICBtb2Rvbmx5VHRyZW5kIDwtIHJlYWRSRFMoJ3RlbXAvbW9kb25seVR0cmVuZC5yZHMnKQp9IGVsc2UgewogIG1vZG9ubHlUdHJlbmQgPC0gbG1lKEp0dXRyZW5kIH4gYWJzKHRlbXB0cmVuZCkqUkVBTE0sCiAgICAgICAgICAgICAgICAgICByYW5kb20gPSByYW5kZWYsIHdlaWdodHMgPSB2YXJlZiwgZGF0YSA9IHRyZW5kc1tpLF0sIG1ldGhvZCA9ICdSRU1MJykKICBzYXZlUkRTKG1vZG9ubHlUdHJlbmQsIGZpbGUgPSAndGVtcC9tb2Rvbmx5VHRyZW5kLnJkcycpCn0KCmkyIDwtIHRyZW5kc1ssIGNvbXBsZXRlLmNhc2VzKEpiZXRhdHJlbmQsIFJFQUxNLCB0ZW1wdHJlbmQpXQppZihmaWxlLmV4aXN0cygndGVtcC9tb2Rvbmx5VHRyZW5kSmJldGEucmRzJykpewogIG1vZG9ubHlUdHJlbmRKYmV0YSA8LSByZWFkUkRTKCd0ZW1wL21vZG9ubHlUdHJlbmRKYmV0YS5yZHMnKQp9IGVsc2UgewogIG1vZG9ubHlUdHJlbmRKYmV0YSA8LSBsbWUoSmJldGF0cmVuZCB+IGFicyh0ZW1wdHJlbmQpKlJFQUxNLAogICAgICAgICAgICAgICAgICAgcmFuZG9tID0gcmFuZGVmLCB3ZWlnaHRzID0gdmFyZWYsIGRhdGEgPSB0cmVuZHNbaTIsXSwgbWV0aG9kID0gJ1JFTUwnLCAKICAgICAgICAgICAgICAgICAgIGNvbnRyb2w9bG1lQ29udHJvbChtc01heEl0ZXIgPSAxMDAsIG1heEl0ZXIgPSAxMDApKQogIHNhdmVSRFMobW9kb25seVR0cmVuZEpiZXRhLCBmaWxlID0gJ3RlbXAvbW9kb25seVR0cmVuZEpiZXRhLnJkcycpCn0KCmkzIDwtIHRyZW5kc1ssIGNvbXBsZXRlLmNhc2VzKEhvcm50cmVuZCwgUkVBTE0sIHRlbXB0cmVuZCldCmlmKGZpbGUuZXhpc3RzKCd0ZW1wL21vZG9ubHlUdHJlbmRIb3JuLnJkcycpKXsKICBtb2Rvbmx5VHRyZW5kSG9ybiA8LSByZWFkUkRTKCd0ZW1wL21vZG9ubHlUdHJlbmRIb3JuLnJkcycpCn0gZWxzZSB7CiAgbW9kb25seVR0cmVuZEhvcm4gPC0gbG1lKEhvcm50cmVuZCB+IGFicyh0ZW1wdHJlbmQpKlJFQUxNLAogICAgICAgICAgICAgICAgICAgcmFuZG9tID0gcmFuZGVmLCB3ZWlnaHRzID0gdmFyZWYsIGRhdGEgPSB0cmVuZHNbaTMsXSwgbWV0aG9kID0gJ1JFTUwnKQogIHNhdmVSRFMobW9kb25seVR0cmVuZEhvcm4sIGZpbGUgPSAndGVtcC9tb2Rvbmx5VHRyZW5kSG9ybi5yZHMnKQp9CgpzdW1tYXJ5KG1vZG9ubHlUdHJlbmQpCnN1bW1hcnkobW9kb25seVR0cmVuZEpiZXRhKQpzdW1tYXJ5KG1vZG9ubHlUdHJlbmRIb3JuKQoKCmBgYAoKCgojIyMgUGxvdCB0aGUgdGVtcC1vbmx5IGNvZWZmaWNpZW50cwpgYGB7ciBtb2Rvbmx5VHRyZW5kc2ltcCBjb2Vmc30KIyBtYWtlIHRhYmxlIG9mIGNvZWZmaWNpZW50cwpjb2VmcyA8LSBhcy5kYXRhLmZyYW1lKHN1bW1hcnkobW9kb25seVR0cmVuZCkkdFRhYmxlKQpjb2VmczIgPC0gYXMuZGF0YS5mcmFtZShzdW1tYXJ5KG1vZG9ubHlUdHJlbmRKYmV0YSkkdFRhYmxlKQpjb2VmczMgPC0gYXMuZGF0YS5mcmFtZShzdW1tYXJ5KG1vZG9ubHlUdHJlbmRIb3JuKSR0VGFibGUpCmNvZWZzJG1vZCA8LSAnSnR1Jwpjb2VmczIkbW9kIDwtICdKYmV0YScKY29lZnMzJG1vZCA8LSAnSG9ybicKcm93czEgPC0gd2hpY2goZ3JlcGwoJ3RlbXB0cmVuZCcsIHJvd25hbWVzKGNvZWZzKSkpICMgZXh0cmFjdCB0ZW1wZXJhdHVyZSBlZmZlY3QKY29scyA8LSBjKCdWYWx1ZScsICdTdGQuRXJyb3InLCAnbW9kJykKYWxsY29lZnMgPC0gcmJpbmQoY29lZnNbcm93czEsIGNvbHNdLCBjb2VmczJbcm93czEsIGNvbHNdLCBjb2VmczNbcm93czEsIGNvbHNdKQphbGxjb2VmcyRWYWx1ZVtncmVwbCgnUkVBTE1NYXJpbmUnLCByb3duYW1lcyhhbGxjb2VmcykpXSA8LSAKICBhbGxjb2VmcyRWYWx1ZVtncmVwbCgnUkVBTE1NYXJpbmUnLCByb3duYW1lcyhhbGxjb2VmcykpXSArIAogIGFsbGNvZWZzJFZhbHVlWyFncmVwbCgnUkVBTE0nLCByb3duYW1lcyhhbGxjb2VmcykpXSAjIGFkZCBpbnRlcmNlcHQgdG8gbWFyaW5lIGVmZmVjdHMKYWxsY29lZnMkVmFsdWVbZ3JlcGwoJ1JFQUxNVGVycmVzdHJpYWwnLCByb3duYW1lcyhhbGxjb2VmcykpXSA8LSAKICBhbGxjb2VmcyRWYWx1ZVtncmVwbCgnUkVBTE1UZXJyZXN0cmlhbCcsIHJvd25hbWVzKGFsbGNvZWZzKSldICsgCiAgYWxsY29lZnMkVmFsdWVbIWdyZXBsKCdSRUFMTScsIHJvd25hbWVzKGFsbGNvZWZzKSldICMgYWRkIGludGVyY2VwdCB0byB0ZXJyZXN0cmlhbCBlZmZlY3RzCgphbGxjb2VmcyRsQ0kgPC0gYWxsY29lZnMkVmFsdWUgLSBhbGxjb2VmcyRTdGQuRXJyb3IgIyBsb3dlciBjb25maWRlbmNlIGludGVydmFsCmFsbGNvZWZzJHVDSSA8LSBhbGxjb2VmcyRWYWx1ZSArIGFsbGNvZWZzJFN0ZC5FcnJvcgphbGxjb2VmcyR5IDwtIGMoMywgMiwgMSwgMi45LCAxLjksIDAuOSwgMi44LCAxLjgsIDAuOCkgIyB5LXZhbHVlcwphbGxjb2VmcyRjb2wgPC0gYyhyZXAoJ2JsYWNrJywgMyksIHJlcCgnbGlnaHQgZ3JleScsIDMpLCByZXAoJ2RhcmsgZ3JleScsIDMpKQphbGxjb2VmcyRyZWFsbSA8LSByZXAoYygnRnJlc2h3YXRlcicsICdNYXJpbmUnLCAnVGVycmVzdHJpYWwnKSwgMykKCnBhcihsYXMgPSAxLCBtYWkgPSBjKDAuOCwgMiwgMC4xLCAwLjEpKQpwbG90KDAsMCwgY29sID0gJ3doaXRlJywgeGxpbT1jKC0wLjAyLCAwLjg1KSwgeWxpbSA9IGMoMC43LDMpLCAKICAgICB5YXh0PSduJywgeGxhYiA9ICdUdXJub3ZlciBwZXIgfMKwQy95cnwnLCB5bGFiID0nJykKYXhpcygyLCBhdCA9IDM6MSwgbGFiZWxzID0gYygnRnJlc2h3YXRlcicsICdNYXJpbmUnLCAnVGVycmVzdHJpYWwnKSwgY2V4LmF4aXMgPSAwLjcpCmFibGluZSh2ID0gMCwgY29sID0gJ2dyZXknKQpmb3IoaSBpbiAxOm5yb3coYWxsY29lZnMpKXsKICB3aXRoKGFsbGNvZWZzW2ksIF0sIHBvaW50cyhWYWx1ZSwgeSwgcGNoID0gMTYsIGNvbCA9IGNvbCkpCiAgd2l0aChhbGxjb2Vmc1tpLCBdLCBsaW5lcyh4ID0gYyhsQ0ksIHVDSSksIHkgPSBjKHksIHkpLCBjb2wgPSBjb2wpKQp9CmxlZ2VuZCgnYm90dG9tcmlnaHQnLCBjb2wgPSBjKCdibGFjaycsICdkYXJrIGdyZXknLCAnbGlnaHQgZ3JleScpLCBsd2QgPSAxLCBwY2ggPSAxNiwgCiAgICAgICBsZWdlbmQgPSBjKCdKYWNjYXJkIHR1cm5vdmVyJywgJ0phY2NhcmQgdG90YWwnLCAnSG9ybi1Nb3Jpc2l0YScpKQoKYGBgCiMjIyBOaWNlciBwbG90cyBvZiB0dXJub3ZlciB2cy4gdGVtcGVyYXR1cmUgZGF0YSBhbmQgbW9kZWwgZml0ClNjYXR0ZXJwbG90LCB2aW9saW4gcGxvdHMsIGFuZCBjb2VmZmljaWVudCBwbG90cyBhbGwgdG9nZXRoZXIKYGBge3IgdHVybm92ZXIgdnMuIHRlbXBlcmF0dXJlIGJpZyBwbG90LCBmaWcud2lkdGg9NiwgZmlnLmhlaWdodD00LjV9CiMgb24gbWFjYm9vazogZmlnLndpZHRoPTMsIGZpZy5oZWlnaHQ9Mi4zNzUsIGZpZy5yZXRpbmE9Mywgb3V0LndpZHRoPTMsIG91dC5oZWlnaHQ9Mi4zNzUKIyBvbiBleHRlcm5hbCBtb25pdG9yOiBmaWcud2lkdGg9NiwgZmlnLmhlaWdodD00LjUKdHJlbmRzW3RlbXB0cmVuZCA8PSAtMC41LCB0ZW1wdHJlbmR0ZXh0IDo9ICdDb29saW5nJ10KdHJlbmRzW2Ficyh0ZW1wdHJlbmQpIDw9IDAuMSwgdGVtcHRyZW5kdGV4dCA6PSAnU3RhYmxlJ10KdHJlbmRzW3RlbXB0cmVuZCA+PSAwLjUsIHRlbXB0cmVuZHRleHQgOj0gJ1dhcm1pbmcnXQoKdHJlbmRzW2FicyhyYXJlZnlJRF95KSA8IDM1LCBsYXR6b25lIDo9ICdTdWJ0cm9waWNzJ10KdHJlbmRzW2FicyhyYXJlZnlJRF95KSA+PSAzNSAmIGFicyhyYXJlZnlJRF94KSA8IDY2LjU2MzM5LCBsYXR6b25lIDo9ICdUZW1wZXJhdGUnXSAKdHJlbmRzW2FicyhyYXJlZnlJRF95KSA+PSA2Ni41NjMzOSwgbGF0em9uZSA6PSAnUG9sYXInXQp0cmVuZHNbLCBsYXR6b25lIDo9IGZhY3RvcihsYXR6b25lLCBsZXZlbHMgPSBjKCdTdWJ0cm9waWNzJywgJ1RlbXBlcmF0ZScsICdQb2xhcicpKV0KCnAxIDwtIGdncGxvdCh0cmVuZHMsIGFlcyh0ZW1wdHJlbmQsIEp0dXRyZW5kLCBjb2xvciA9IFJFQUxNLCBmaWxsID0gUkVBTE0sIHNpemUgPSBueXJCVCkpICsKICBnZW9tX3BvaW50KG5hLnJtID0gVFJVRSwgc2hhcGUgPSAxNiwgYWxwaGEgPSAwLjEpICsgCiAgZ2VvbV9zbW9vdGgoZGF0YT1zdWJzZXQodHJlbmRzLCBhYnModGVtcHRyZW5kKSA8IDAuNzUpLCBtZXRob2QgPSAnZ2FtJywgZm9ybXVsYSA9IHkgfiBzKHgsIGJzID0gImNzIiksIAogICAgICAgICAgICAgIG5hLnJtID0gVFJVRSkgKwogIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlPSJTZXQxIiwgbmFtZSA9ICdSZWFsbScpICsgCiAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZT0iU2V0MSIsIG5hbWUgPSAnUmVhbG0nKSArIAogIGxhYnMoeCA9ICdUZW1wZXJhdHVyZSB0cmVuZCAowrBDL3lyKScsIHkgPSAnSmFjY2FyZCB0dXJub3ZlcicsIHRhZyA9ICdBJykgKwogIHNjYWxlX3NpemVfY29udGludW91cyhyYW5nZSA9IGMoMSwgOCksIGJyZWFrcyA9IGMoMiwgNSwgMjApKSArCiAgZ3VpZGVzKHNpemUgPSBndWlkZV9sZWdlbmQodGl0bGUgPSAnWWVhcnMnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIG92ZXJyaWRlLmFlcyA9IGxpc3QobGluZXR5cGU9MCwgZmlsbCA9IE5BLCBhbHBoYSA9IDEpKSkgKwogIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2JsYW5rKCksIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwgYXhpcy5saW5lID0gZWxlbWVudF9saW5lKGNvbG91ciA9ICJibGFjayIpLAogICAgICAgIGxlZ2VuZC5rZXk9ZWxlbWVudF9ibGFuaygpLAogICAgICAgIGxlZ2VuZC5rZXkuc2l6ZSA9IHVuaXQoMC41LCJsaW5lIiksIAogICAgICAgIGF4aXMudGV4dD1lbGVtZW50X3RleHQoc2l6ZT04KSwKICAgICAgICBheGlzLnRpdGxlPWVsZW1lbnRfdGV4dChzaXplPTEwKSkKCnAyIDwtIGdncGxvdCh0cmVuZHNbIWlzLm5hKHRlbXB0cmVuZHRleHQpLCBdLCBhZXModGVtcHRyZW5kdGV4dCwgSnR1dHJlbmQpKSArCiAgZ2VvbV92aW9saW4oZHJhd19xdWFudGlsZXMgPSBjKDAuMjUsIDAuNSwgMC43NSksIGZpbGwgPSAnZ3JleScpICsKICBsYWJzKHggPSAnJywgeSA9ICdKYWNjYXJkIHR1cm5vdmVyJywgdGFnID0gJ0InKSArCiAgdGhlbWUocGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfYmxhbmsoKSwgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLCBheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gImJsYWNrIiksCiAgICAgICAgbGVnZW5kLmtleT1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0PWVsZW1lbnRfdGV4dChzaXplPTgpLAogICAgICAgIGF4aXMudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9MTApKQoKcDMgPC0gZ2dwbG90KHRyZW5kc1thYnModGVtcHRyZW5kKSA+PSAwLjUgJiAhaXMubmEobGF0em9uZSksIF0sIGFlcyhsYXR6b25lLCBKdHV0cmVuZCkpICsKICBnZW9tX3Zpb2xpbihkcmF3X3F1YW50aWxlcyA9IGMoMC4yNSwgMC41LCAwLjc1KSwgZmlsbCA9ICdncmV5JykgKyAKICBsYWJzKHggPSAnJywgeSA9ICcnLCB0YWcgPSAnQycpICsKICB0aGVtZShwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9ibGFuaygpLCBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksIGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiYmxhY2siKSwKICAgICAgICBsZWdlbmQua2V5PWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRleHQ9ZWxlbWVudF90ZXh0KHNpemU9NyksCiAgICAgICAgYXhpcy50aXRsZT1lbGVtZW50X3RleHQoc2l6ZT0xMCkpCgpwNCA8LSBnZ3Bsb3QoYWxsY29lZnMsIGFlcyhWYWx1ZSwgeSwgZ3JvdXAgPSBtb2QsIGNvbG9yID0gbW9kKSkgKwogIGdlb21fZXJyb3JiYXJoKGFlcyh4bWluID0gbENJLCB4bWF4ID0gdUNJLCBoZWlnaHQgPSAwKSkgKyAKICBnZW9tX3BvaW50KCkgKyAKICBsYWJzKHggPSBleHByZXNzaW9uKGF0b3AoJ1RlbXBlcmF0dXJlIGNoYW5nZSBlZmZlY3QnLCAnKFR1cm5vdmVyICd+ZGVncmVlKidDJ14nLTEnKicpJykpLCB5ID0gJycsIHRhZyA9ICdEJykgKwogIHNjYWxlX2NvbG9yX2dyZXkoKSArIAogIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2JsYW5rKCksIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwgYXhpcy5saW5lID0gZWxlbWVudF9saW5lKGNvbG91ciA9ICJibGFjayIpLAogICAgICAgIGxlZ2VuZC5wb3NpdGlvbj0nbm9uZScsCiAgICAgICAgYXhpcy50ZXh0PWVsZW1lbnRfdGV4dChzaXplPTcpLAogICAgICAgIGF4aXMudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9NykpICsgCiAgY29vcmRfY2FydGVzaWFuKHhsaW0gPWMoMCwgMSkpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobmFtZSA9ICcnLCBicmVha3MgPSBjKDEsIDIsIDMpLCBsYWJlbHMgPSBjKCdUZXJyZXN0cmlhbCcsICdNYXJpbmUnLCAnRnJlc2h3YXRlcicpKQoKZ3JpZC5hcnJhbmdlKHAxLCBwMiwgcDMsIHA0LCBuY29sID0gMywgbGF5b3V0X21hdHJpeCA9IHJiaW5kKGMoMSwxLDEpLCBjKDIsMyw0KSksCiAgICAgICAgICAgICBoZWlnaHRzPWModW5pdCgwLjY2LCAibnBjIiksIHVuaXQoMC4zNCwgIm5wYyIpKSkKYGBgCgojIyBGdWxsIG1vZGVscwpUcnkgc3RhdGljIGNvdmFyaWF0ZXMgcGx1cyBpbnRlcmFjdGlvbnMgb2YgYWJzIHRlbXBlcmF0dXJlIHRyZW5kIHdpdGggZWFjaCBjb3ZhcmlhdGU6CgotIHJlYWxtCi0gZW52aXJvbm1lbnRhbCB0ZW1wZXJhdHVyZQotIGF2ZXJhZ2UgbWV0YWJvbGljIHRlbXBlcmF0dXJlCi0gc2Vhc29uYWxpdHkKLSBtaWNyb2NsaW1hdGVzCi0gTlBQCi0gc3BlZWQKLSBtYXNzCi0gbGlmZXNwYW4KLSBjb25zdW1lciB2cy4gcHJvZHVjZXIKLSB0aGVybWFsIGJpYXMKCkV4Y2VwdCBmb3IgdGhlcm1hbCBiaWFzOiBpbnRlcmFjdCB3aXRoIHRlbXBlcmF0dXJlIHRyZW5kIChub3QgYWJzKQoKIyMjIEZ1bGwgbW9kZWwgZm9yIEphY2NhcmQgdG90YWwKYGBge3IgTE1FIEphY2FyZCB0dXJub3ZlciB0ZW1wZXJhdHVyZSBmdWxsfQppIDwtIHRyZW5kc1ssIGNvbXBsZXRlLmNhc2VzKEp0dXRyZW5kLCBSRUFMTSwgdGVtcGF2ZS5zYywgdGVtcGF2ZV9tZXRhYi5zYywgc2Vhcy5zYywgbWljcm9jbGltLnNjLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZW1wdHJlbmQuc2MsIHRlbXB0cmVuZF9hYnMuc2MsIG1hc3Muc2MsIHNwZWVkLnNjLCBsaWZlc3Bhbi5zYywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3VtZXJmcmFjLnNjLCBlbmRvdGhlcm1mcmFjLnNjLCBuc3BwLnNjLCB0aGVybWFsX2JpYXMuc2MsIG5wcC5zYywgaHVtYW4uc2MpXQoKcmFuZGVmIDwtIGxpc3QoU1RVRFlfSUQgPSB+IHRlbXB0cmVuZF9hYnMuc2MsIHJhcmVmeUlEID0gfjEpCnZhcmVmIDwtIHZhclBvd2VyKC0wLjUsIH5ueXJCVCkKCmlmKGZpbGUuZXhpc3RzKCd0ZW1wL21vZFRmdWxsMS5yZHMnKSl7CiAgbW9kVGZ1bGwxIDwtIHJlYWRSRFMoJ3RlbXAvbW9kVGZ1bGwxLnJkcycpCn0gZWxzZSB7CiAgbW9kVGZ1bGwxIDwtIGxtZShKdHV0cmVuZCB+IHRlbXB0cmVuZF9hYnMuc2MqUkVBTE0gKyAKICAgICAgICAgICAgICAgICAgICAgdGVtcHRyZW5kX2Ficy5zYyp0ZW1wYXZlLnNjICsKICAgICAgICAgICAgICAgICAgICAgdGVtcHRyZW5kX2Ficy5zYyp0ZW1wYXZlX21ldGFiLnNjICsgCiAgICAgICAgICAgICAgICAgICAgIHRlbXB0cmVuZF9hYnMuc2Mqc2Vhcy5zYyArIAogICAgICAgICAgICAgICAgICAgICB0ZW1wdHJlbmRfYWJzLnNjKm1pY3JvY2xpbS5zYyArIAogICAgICAgICAgICAgICAgICAgICB0ZW1wdHJlbmRfYWJzLnNjKm1hc3Muc2MgKyAKICAgICAgICAgICAgICAgICAgICAgdGVtcHRyZW5kX2Ficy5zYypzcGVlZC5zYyArIAogICAgICAgICAgICAgICAgICAgICB0ZW1wdHJlbmRfYWJzLnNjKmxpZmVzcGFuLnNjICsgCiAgICAgICAgICAgICAgICAgICAgIHRlbXB0cmVuZF9hYnMuc2MqY29uc3VtZXJmcmFjLnNjICsKICAgICAgICAgICAgICAgICAgICAgdGVtcHRyZW5kX2Ficy5zYyplbmRvdGhlcm1mcmFjLnNjICsKICAgICAgICAgICAgICAgICAgICAgdGVtcHRyZW5kX2Ficy5zYypuc3BwLnNjICsKICAgICAgICAgICAgICAgICAgICAgdGVtcHRyZW5kLnNjKnRoZXJtYWxfYmlhcy5zYyArCiAgICAgICAgICAgICAgICAgICAgIHRlbXB0cmVuZF9hYnMuc2MqbnBwLnNjICsKICAgICAgICAgICAgICAgICAgICAgdGVtcHRyZW5kX2Ficy5zYypodW1hbi5zYzpSRUFMTTIsCiAgICAgICAgICAgICAgICAgICByYW5kb20gPSByYW5kZWYsIHdlaWdodHMgPSB2YXJlZiwgZGF0YSA9IHRyZW5kc1tpLF0sIG1ldGhvZCA9ICdSRU1MJykKICBzYXZlUkRTKG1vZFRmdWxsMSwgZmlsZSA9ICd0ZW1wL21vZFRmdWxsMS5yZHMnKQp9CgpzdW1tYXJ5KG1vZFRmdWxsMSkKCgpgYGAKCgoKIyMjIyBQbG90IHRoZSBjb2VmZmljaWVudHMgZnJvbSB0aGUgZnVsbCBtb2RlbApgYGB7ciBwbG90IGZ1bGxUbW9kMSwgZmlnLmhlaWdodD02LCBmaWcud2lkdGg9N30KCmNvZWZzIDwtIHN1bW1hcnkobW9kVGZ1bGwxKSR0VGFibGUKcGFyKGxhcyA9IDEsIG1haSA9IGMoMC41LCAzLCAwLjEsIDAuMSkpCnJvd3MxIDwtIHdoaWNoKCFncmVwbCgnSW50ZXJjZXB0Jywgcm93bmFtZXMoY29lZnMpKSkKcGxvdCgwLDAsIGNvbCA9ICd3aGl0ZScsIHhsaW09YygtMC4wNSwgMC4wOCksIHlsaW0gPSBjKDEsbGVuZ3RoKHJvd3MxKSksIHlheHQ9J24nLCB4bGFiID0gJycsIHlsYWIgPScnKQpheGlzKDIsIGF0ID0gbGVuZ3RoKHJvd3MxKToxLCBsYWJlbHMgPSByb3duYW1lcyhjb2Vmcylbcm93czFdLCBjZXguYXhpcyA9IDAuNykKYWJsaW5lKHYgPSAwLCBjb2wgPSAnZ3JleScpCmZvcihpIGluIDE6bGVuZ3RoKHJvd3MxKSl7CiAgeCA9IGNvZWZzW3Jvd3MxW2ldLCAxXQogIHNlID0gY29lZnNbcm93czFbaV0sIDJdCiAgcG9pbnRzKHgsIGxlbmd0aChyb3dzMSkgKyAxIC0gaSwgcGNoID0gMTYpCiAgbGluZXMoeCA9IGMoeC1zZSwgeCtzZSksIHkgPSBjKGxlbmd0aChyb3dzMSkgKyAxIC0gaSwgbGVuZ3RoKHJvd3MxKSArIDEgLSBpKSkKfQpgYGAKCiMjIyMgUGxvdCBpbnRlcmFjdGlvbnMKYGBge3IgaW50ZXJhY3Rpb24gcGxvdHMgbW9kVGZ1bGwxfQojIG5zcHAgZWZmZWN0CiMgdHJlbmRzWywgcmFuZ2UoTnNwcCldICMgMjoxNDI3CiMgdHJlbmRzWywgcmFuZ2UodGVtcHRyZW5kLCBuYS5ybSA9IFRSVUUpXSAjIC0xLjMgdG8gMS45CiMgd2hpY2gubWluKGFicyhyYW5lZihtb2RUZnVsbDFzaW1wcmVtbCkkU1RVRFlfSUQkYChJbnRlcmNlcHQpYCkpICMgc3R1ZHkgMTI3IGhhcyByYW5lZnMgbmVhciAwCiMgdHJlbmRzW1NUVURZX0lEID09IDEyNywgc29ydCh1bmlxdWUocmFyZWZ5SUQpKV0gIyByYW5lZnMgbmVhciB6ZXJvIGZvciAxMjdfNTE0NjY4CiMgCgpuZXdkYXQgPC0gY2JpbmQoZXhwYW5kLmdyaWQodGVtcHRyZW5kID0gc2VxKC0xLjMsIDIsIGxlbmd0aC5vdXQgPSAxMDApLCBuc3BwID0gMl5zZXEoMSwgOSwgbGVuZ3RoLm91dD01MDApKSwgCiAgICAgICAgICAgICAgICBkYXRhLnRhYmxlKFJFQUxNID0gJ0ZyZXNod2F0ZXInLCBSRUFMTTIgPSAnVGVyckZyZXNoJywgdGVtcGF2ZS5zYyA9IDAsIHRlbXBhdmVfbWV0YWIuc2MgPSAwLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgc2Vhcy5zYyA9IDAsIG1pY3JvY2xpbS5zYyA9IDAsIG1hc3Muc2MgPSAwLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgc3BlZWQuc2MgPSAwLCBsaWZlc3Bhbi5zYyA9IDAsIGVuZG90aGVybWZyYWMuc2MgPSAwLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhlcm1hbF9iaWFzLnNjID0gMCwgbnBwLnNjID0gMCwgaHVtYW4uc2MgPSAwLAogICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdW1lcmZyYWMuc2MgPSAwLAogICAgICAgICAgICAgICAgICAgICAgICAgICBueXJCVCA9IDIwLCBTVFVEWV9JRCA9IDEyN0wsIHJhcmVmeUlEID0gJzEyN181MTQ2NjgnKSkKbmV3ZGF0IDwtIHJiaW5kKG5ld2RhdFsxOjIsIF0sIG5ld2RhdCkgIyBhZGQgdHdvIGV4dHJhIHJvd3Mgc28gdGhhdCBhbGwgZmFjdG9yIGxldmVscyBhcmUgcmVwcmVzZW50ZWQgKGZvciBwcmVkaWN0LmxtZSB0byB3b3JrKQpuZXdkYXQkUkVBTE1bMToyXSA8LSBjKCdNYXJpbmUnLCAnVGVycmVzdHJpYWwnKQpuZXdkYXQkUkVBTE0yWzE6Ml0gPC0gYygnTWFyaW5lJywgJ01hcmluZScpCgojIHNjYWxlIHRoZSB2YXJzCm5ld2RhdCRuc3BwLnNjIDwtIChsb2cobmV3ZGF0JG5zcHApIC0gYXR0cih0cmVuZHMkbnNwcC5zYywgJ3NjYWxlZDpjZW50ZXInKSkvYXR0cih0cmVuZHMkbnNwcC5zYywgJ3NjYWxlZDpzY2FsZScpCm5ld2RhdCR0ZW1wdHJlbmQuc2MgPC0gKG5ld2RhdCR0ZW1wdHJlbmQgLSBhdHRyKHRyZW5kcyR0ZW1wdHJlbmQuc2MsICdzY2FsZWQ6Y2VudGVyJykpL2F0dHIodHJlbmRzJHRlbXB0cmVuZC5zYywgJ3NjYWxlZDpzY2FsZScpIApuZXdkYXQkdGVtcHRyZW5kX2FicyA8LSBhYnMobmV3ZGF0JHRlbXB0cmVuZCkKbmV3ZGF0JHRlbXB0cmVuZF9hYnMuc2MgPC0gKChuZXdkYXQkdGVtcHRyZW5kX2FicykgLSBhdHRyKHRyZW5kcyR0ZW1wdHJlbmRfYWJzLnNjLCAnc2NhbGVkOmNlbnRlcicpKS9hdHRyKHRyZW5kcyR0ZW1wdHJlbmRfYWJzLnNjLCAnc2NhbGVkOnNjYWxlJykKCm5ld2RhdCA8LSBuZXdkYXRbaXMuZmluaXRlKG5ld2RhdCR0ZW1wdHJlbmRfYWJzLnNjKSxdCgojIG1ha2UgcHJlZGljdGlvbnMKbmV3ZGF0JHByZWRzIDwtIHByZWRpY3Qob2JqZWN0ID0gbW9kVGZ1bGwxLCBuZXdkYXRhID0gbmV3ZGF0LCBsZXZlbCA9IDApCgojcmVtb3ZlIHRoZSBleHRyYSByb3dzCm5ld2RhdCA8LSBuZXdkYXRbbmV3ZGF0JFJFQUxNID09ICdGcmVzaHdhdGVyJywgXQoKIyBwbG90CmdncGxvdChuZXdkYXQsIGFlcyh0ZW1wdHJlbmQsIHByZWRzLCBncm91cCA9IG5zcHAsIGNvbG9yID0gbnNwcCkpICsKICBnZW9tX2xpbmUoKSArCiAgc2NhbGVfY29sb3JfZGlzdGlsbGVyKHBhbGV0dGUgPSAiWWxHbkJ1IiwgdHJhbnMgPSAnbG9nJywgYnJlYWtzID0gYygyLCAxMCwgNTAsIDUwMCkpCmBgYAoKCiMjIyMgUGxvdCByZXNpZHVhbHMgYWdhaW5zdCBlYWNoIHByZWRpY3RvcgpgYGB7ciByZXNpZHMgbW9kVGZ1bGwxLCBmaWcuaGVpZ2h0ID0gMTAsIGZpZy53aWR0aD0xMH0KcmVzaWRzIDwtIHJlc2lkKG1vZFRmdWxsMSkKcHJlZHMgPC0gZ2V0RGF0YShtb2RUZnVsbDEpCmNvbCA9ICcjMDAwMDAwMzMnCmNleCA9IDAuNQpwYXIobWZyb3cgPSBjKDQsNCkpCmJveHBsb3QocmVzaWRzIH4gcHJlZHMkUkVBTE0sIGNleCA9IGNleCwgY29sID0gY29sKQpwbG90KHByZWRzJHRlbXB0cmVuZF9hYnMuc2MsIHJlc2lkcywgY2V4ID0gY2V4LCBjb2wgPSBjb2wpCnBsb3QocHJlZHMkdGVtcHRyZW5kLnNjLCByZXNpZHMsIGNleCA9IGNleCwgY29sID0gY29sKQpwbG90KHByZWRzJHRlbXBhdmUuc2MsIHJlc2lkcywgY2V4ID0gY2V4LCBjb2wgPSBjb2wpCnBsb3QocHJlZHMkdGVtcGF2ZV9tZXRhYi5zYywgcmVzaWRzLCBjZXggPSBjZXgsIGNvbCA9IGNvbCkKcGxvdChwcmVkcyRzZWFzLnNjLCByZXNpZHMsIGNleCA9IGNleCwgY29sID0gY29sKQpwbG90KHByZWRzJG1pY3JvY2xpbS5zYywgcmVzaWRzLCBjZXggPSBjZXgsIGNvbCA9IGNvbCkKcGxvdChwcmVkcyRtYXNzLnNjLCByZXNpZHMsIGNleCA9IGNleCwgY29sID0gY29sKQpwbG90KHByZWRzJHNwZWVkLnNjLCByZXNpZHMsIGNleCA9IGNleCwgY29sID0gY29sKQpwbG90KHByZWRzJGxpZmVzcGFuLnNjLCByZXNpZHMsIGNleCA9IGNleCwgY29sID0gY29sKQpwbG90KHByZWRzJGNvbnN1bWVyZnJhYy5zYywgcmVzaWRzLCBjZXggPSBjZXgsIGNvbCA9IGNvbCkKcGxvdChwcmVkcyRlbmRvdGhlcm1mcmFjLnNjLCByZXNpZHMsIGNleCA9IGNleCwgY29sID0gY29sKQpwbG90KHByZWRzJG5zcHAuc2MsIHJlc2lkcywgY2V4ID0gY2V4LCBjb2wgPSBjb2wpCnBsb3QocHJlZHMkdGhlcm1hbF9iaWFzLnNjLCByZXNpZHMsIGNleCA9IGNleCwgY29sID0gY29sKQpwbG90KHByZWRzJG5wcC5zYywgcmVzaWRzLCBjZXggPSBjZXgsIGNvbCA9IGNvbCkKcGxvdChwcmVkcyRodW1hbi5zYywgcmVzaWRzLCBjZXggPSBjZXgsIGNvbCA9IGNvbCkKYGBgCgojIyMgU2Vuc2l0aXZpdHkgYW5hbHlzaXM6IHRvdGFsIHR1cm5vdmVyIGFuZCBIb3JuLU1vcmlzaXRhIG1vZGVscwojIyMjIEZpdCBmdWxsIG1vZGVscyBmb3IgdG90YWwgYW5kIEhNCmBgYHtyIExNRSBKYWNhcmQgdG90YWwgYW5kIE1IIG1vZGVscywgZmlnLndpZHRoPTEwLCBmaWcuaGVpZ2h0PTh9CmkyIDwtIHRyZW5kc1ssIGNvbXBsZXRlLmNhc2VzKEpiZXRhdHJlbmQsIFJFQUxNLCB0ZW1wYXZlLnNjLCB0ZW1wYXZlX21ldGFiLnNjLCBzZWFzLnNjLCBtaWNyb2NsaW0uc2MsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRlbXB0cmVuZC5zYywgdGVtcHRyZW5kX2Ficy5zYywgbWFzcy5zYywgc3BlZWQuc2MsIGxpZmVzcGFuLnNjLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdW1lcmZyYWMuc2MsIGVuZG90aGVybWZyYWMuc2MsIG5zcHAuc2MsIHRoZXJtYWxfYmlhcy5zYywgbnBwLnNjLCBodW1hbi5zYyldCmkzIDwtIHRyZW5kc1ssIGNvbXBsZXRlLmNhc2VzKEhvcm50cmVuZCwgUkVBTE0sIHRlbXBhdmUuc2MsIHRlbXBhdmVfbWV0YWIuc2MsIHNlYXMuc2MsIG1pY3JvY2xpbS5zYywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGVtcHRyZW5kLnNjLCB0ZW1wdHJlbmRfYWJzLnNjLCBtYXNzLnNjLCBzcGVlZC5zYywgbGlmZXNwYW4uc2MsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN1bWVyZnJhYy5zYywgZW5kb3RoZXJtZnJhYy5zYywgbnNwcC5zYywgdGhlcm1hbF9iaWFzLnNjLCBucHAuc2MsIGh1bWFuLnNjKV0KCnJhbmRlZiA8LSBsaXN0KFNUVURZX0lEID0gfiB0ZW1wdHJlbmRfYWJzLnNjLCByYXJlZnlJRCA9IH4xKQp2YXJlZiA8LSB2YXJQb3dlcigtMC41LCB+bnlyQlQpCgojIGZ1bGwgbW9kZWxzCmlmKGZpbGUuZXhpc3RzKCd0ZW1wL21vZFRmdWxsSmJldGEucmRzJykpewogIG1vZFRmdWxsSmJldGEgPC0gcmVhZFJEUygndGVtcC9tb2RUZnVsbEpiZXRhLnJkcycpCn0gZWxzZSB7CiAgbW9kVGZ1bGxKYmV0YSA8LSBsbWUoSmJldGF0cmVuZCB+IHRlbXB0cmVuZF9hYnMuc2MqUkVBTE0gKyAKICAgICAgICAgICAgICAgICAgICAgdGVtcHRyZW5kX2Ficy5zYyp0ZW1wYXZlLnNjICsKICAgICAgICAgICAgICAgICAgICAgdGVtcHRyZW5kX2Ficy5zYyp0ZW1wYXZlX21ldGFiLnNjICsgCiAgICAgICAgICAgICAgICAgICAgIHRlbXB0cmVuZF9hYnMuc2Mqc2Vhcy5zYyArIAogICAgICAgICAgICAgICAgICAgICB0ZW1wdHJlbmRfYWJzLnNjKm1pY3JvY2xpbS5zYyArIAogICAgICAgICAgICAgICAgICAgICB0ZW1wdHJlbmRfYWJzLnNjKm1hc3Muc2MgKyAKICAgICAgICAgICAgICAgICAgICAgdGVtcHRyZW5kX2Ficy5zYypzcGVlZC5zYyArIAogICAgICAgICAgICAgICAgICAgICB0ZW1wdHJlbmRfYWJzLnNjKmxpZmVzcGFuLnNjICsgCiAgICAgICAgICAgICAgICAgICAgIHRlbXB0cmVuZF9hYnMuc2MqY29uc3VtZXJmcmFjLnNjICsKICAgICAgICAgICAgICAgICAgICAgdGVtcHRyZW5kX2Ficy5zYyplbmRvdGhlcm1mcmFjLnNjICsKICAgICAgICAgICAgICAgICAgICAgdGVtcHRyZW5kX2Ficy5zYypuc3BwLnNjICsKICAgICAgICAgICAgICAgICAgICAgdGVtcHRyZW5kLnNjKnRoZXJtYWxfYmlhcy5zYyArCiAgICAgICAgICAgICAgICAgICAgIHRlbXB0cmVuZF9hYnMuc2MqbnBwLnNjICsKICAgICAgICAgICAgICAgICAgICAgdGVtcHRyZW5kX2Ficy5zYypodW1hbi5zYzpSRUFMTTIsCiAgICAgICAgICAgICAgICAgICByYW5kb20gPSByYW5kZWYsIHdlaWdodHMgPSB2YXJlZiwgZGF0YSA9IHRyZW5kc1tpMixdLCBtZXRob2QgPSAnUkVNTCcpCiAgc2F2ZVJEUyhtb2RUZnVsbEpiZXRhLCBmaWxlID0gJ3RlbXAvbW9kVGZ1bGxKYmV0YS5yZHMnKQp9CgppZihmaWxlLmV4aXN0cygndGVtcC9tb2RUZnVsbEhvcm4ucmRzJykpewogIG1vZFRmdWxsSG9ybiA8LSByZWFkUkRTKCd0ZW1wL21vZFRmdWxsSG9ybi5yZHMnKQp9IGVsc2UgewogIG1vZFRmdWxsSG9ybiA8LSBsbWUoSG9ybnRyZW5kIH4gdGVtcHRyZW5kX2Ficy5zYypSRUFMTSArIAogICAgICAgICAgICAgICAgICAgICB0ZW1wdHJlbmRfYWJzLnNjKnRlbXBhdmUuc2MgKwogICAgICAgICAgICAgICAgICAgICB0ZW1wdHJlbmRfYWJzLnNjKnRlbXBhdmVfbWV0YWIuc2MgKyAKICAgICAgICAgICAgICAgICAgICAgdGVtcHRyZW5kX2Ficy5zYypzZWFzLnNjICsgCiAgICAgICAgICAgICAgICAgICAgIHRlbXB0cmVuZF9hYnMuc2MqbWljcm9jbGltLnNjICsgCiAgICAgICAgICAgICAgICAgICAgIHRlbXB0cmVuZF9hYnMuc2MqbWFzcy5zYyArIAogICAgICAgICAgICAgICAgICAgICB0ZW1wdHJlbmRfYWJzLnNjKnNwZWVkLnNjICsgCiAgICAgICAgICAgICAgICAgICAgIHRlbXB0cmVuZF9hYnMuc2MqbGlmZXNwYW4uc2MgKyAKICAgICAgICAgICAgICAgICAgICAgdGVtcHRyZW5kX2Ficy5zYypjb25zdW1lcmZyYWMuc2MgKwogICAgICAgICAgICAgICAgICAgICB0ZW1wdHJlbmRfYWJzLnNjKmVuZG90aGVybWZyYWMuc2MgKwogICAgICAgICAgICAgICAgICAgICB0ZW1wdHJlbmRfYWJzLnNjKm5zcHAuc2MgKwogICAgICAgICAgICAgICAgICAgICB0ZW1wdHJlbmQuc2MqdGhlcm1hbF9iaWFzLnNjICsKICAgICAgICAgICAgICAgICAgICAgdGVtcHRyZW5kX2Ficy5zYypucHAuc2MgKwogICAgICAgICAgICAgICAgICAgICB0ZW1wdHJlbmRfYWJzLnNjKmh1bWFuLnNjOlJFQUxNMiwKICAgICAgICAgICAgICAgICAgIHJhbmRvbSA9IHJhbmRlZiwgd2VpZ2h0cyA9IHZhcmVmLCBkYXRhID0gdHJlbmRzW2kzLF0sIG1ldGhvZCA9ICdSRU1MJykKICBzYXZlUkRTKG1vZFRmdWxsSG9ybiwgZmlsZSA9ICd0ZW1wL21vZFRmdWxsSG9ybi5yZHMnKQp9CgpzdW1tYXJ5KG1vZFRmdWxsSmJldGEpCnN1bW1hcnkobW9kVGZ1bGxIb3JuKQpgYGAKCiMjIyMgcGxvdCBjb2VmcyBmb3IgZnVsbCBUb3RhbCBhbmQgSE0gbW9kZWxzCmBgYHtyIHBsb3Qgc2ltcGxpZmllZCB0b3RhbCBhbmQgSE0gbW9kIGNvZWZzLCBmaWcuaGVpZ2h0PTgsIGZpZy53aWR0aD02fQpjb2VmczIgPC0gc3VtbWFyeShtb2RUZnVsbEpiZXRhKSR0VGFibGUKY29lZnMzIDwtIHN1bW1hcnkobW9kVGZ1bGxIb3JuKSR0VGFibGUKdmFyc3RvcGxvdCA8LSB1bmlxdWUoYyhyb3duYW1lcyhjb2VmczIpLCByb3duYW1lcyhjb2VmczMpKSkKCnJvd3MxIDwtIHdoaWNoKCFncmVwbCgnSW50ZXJjZXB0JywgdmFyc3RvcGxvdCkgfCBncmVwbCgnOicsIHZhcnN0b3Bsb3QpKSAjIHZhcnMgdG8gcGxvdCBpbiBmaXJzdCBncmFwaApyb3dzMV8yIDwtIHdoaWNoKHJvd25hbWVzKGNvZWZzMikgJWluJSB2YXJzdG9wbG90W3Jvd3MxXSkgIyByb3dzIGluIGNvZWZzMgpyb3dzMV8zIDwtIHdoaWNoKHJvd25hbWVzKGNvZWZzMykgJWluJSB2YXJzdG9wbG90W3Jvd3MxXSkgIyByb3dzIGluIGNvZWZzMwp4bGltczEgPC0gcmFuZ2UoYyhjb2VmczJbcm93czFfMiwxXSAtIGNvZWZzMltyb3dzMV8yLDJdLCAKICAgICAgICAgICAgICAgICAgY29lZnMyW3Jvd3MxXzIsMV0gKyBjb2VmczJbcm93czFfMiwyXSwgCiAgICAgICAgICAgICAgICAgIGNvZWZzM1tyb3dzMV8zLDFdIC0gY29lZnMzW3Jvd3MxXzMsMl0sIAogICAgICAgICAgICAgICAgICBjb2VmczNbcm93czFfMywxXSArIGNvZWZzM1tyb3dzMV8zLDJdKSkKCmNvbHMgPC0gYygnYmxhY2snLCAnZ3JleScpICMgZm9yIEpiZXRhIGFuZCBIb3JuIG1vZGVscywgcmVzcGVjdGl2ZWx5Cm9mZnMxIDwtIDAuMSAjIG9mZnNldCB2ZXJ0aWNhbGx5IGZvciB0aGUgdHdvIG1vZGVscwpvZmZzMiA8LSAwLjAxICMgb2Zmc2V0IHZlcnRpY2FsbHkgZm9yIHRoZSB0d28gbW9kZWxzIChwbG90IDIpCgpwYXIobGFzID0gMSwgbWFpID0gYygwLjUsIDMsIDAuMSwgMC4xKSkKCnBsb3QoMCwwLCBjb2wgPSAnd2hpdGUnLCB4bGltPXhsaW1zMSwgeWxpbSA9IGMoMSxsZW5ndGgocm93czEpKSwgeWF4dD0nbicsIHhsYWIgPSAnJywgeWxhYiA9JycpCmF4aXMoMiwgYXQgPSBsZW5ndGgocm93czEpOjEsIGxhYmVscyA9IHZhcnN0b3Bsb3Rbcm93czFdLCBjZXguYXhpcyA9IDAuNykKYWJsaW5lKHYgPSAwLCBjb2wgPSAnZ3JleScpCmZvcihpIGluIDE6bGVuZ3RoKHJvd3MxKSl7CiAgaWYodmFyc3RvcGxvdFtyb3dzMVtpXV0gJWluJSByb3duYW1lcyhjb2VmczIpKXsKICAgIHggPSBjb2VmczJbcm93bmFtZXMoY29lZnMyKSA9PSB2YXJzdG9wbG90W3Jvd3MxW2ldXSwgMV0KICAgIHNlID0gY29lZnMyW3Jvd25hbWVzKGNvZWZzMikgPT0gdmFyc3RvcGxvdFtyb3dzMVtpXV0sIDJdCiAgICBwb2ludHMoeCwgbGVuZ3RoKHJvd3MxKSArIDEgLSBpICsgb2ZmczEsIHBjaCA9IDE2LCBjb2wgPSBjb2xzWzFdKQogICAgbGluZXMoeCA9IGMoeC1zZSwgeCtzZSksIHkgPSBjKGxlbmd0aChyb3dzMSkgKyAxIC0gaSArIG9mZnMxLCBsZW5ndGgocm93czEpICsgMSAtIGkgKyBvZmZzMSksIGNvbCA9IGNvbHNbMV0pCiAgfQogIGlmKHZhcnN0b3Bsb3Rbcm93czFbaV1dICVpbiUgcm93bmFtZXMoY29lZnMzKSl7CiAgICB4ID0gY29lZnMzW3Jvd25hbWVzKGNvZWZzMykgPT0gdmFyc3RvcGxvdFtyb3dzMVtpXV0sIDFdCiAgICBzZSA9IGNvZWZzM1tyb3duYW1lcyhjb2VmczMpID09IHZhcnN0b3Bsb3Rbcm93czFbaV1dLCAyXQogICAgcG9pbnRzKHgsIGxlbmd0aChyb3dzMSkgKyAxIC0gaSAtIG9mZnMxLCBwY2ggPSAxNiwgY29sID0gY29sc1syXSkKICAgIGxpbmVzKHggPSBjKHgtc2UsIHgrc2UpLCB5ID0gYyhsZW5ndGgocm93czEpICsgMSAtIGkgLSBvZmZzMSwgbGVuZ3RoKHJvd3MxKSArIDEgLSBpIC0gb2ZmczEpLCBjb2wgPSBjb2xzWzJdKQogIH0KfQoKCmBgYAoKQmxhY2sgaXMgZm9yIEphY2NhcmQgdG90YWwgdHVybm92ZXIgKHByZXMvYWJzKSwgZ3JleSBpcyBmb3IgTW9yaXNpdGEtSG9ybiB0dXJub3ZlciAoY29uc2lkZXJzIGFidW5kYW5jZSkKCiMjIyBQbG90IGNvZWZmaWNpZW50cyBmcm9tIGFsbCBmdWxsIG1vZGVscwpgYGB7ciBwbG90IGNvZWZzIGZvciBhbGwgbW9kZWxzLCBmaWcuaGVpZ2h0PTUsIGZpZy53aWR0aD02LCBvdXQuaGVpZ2h0PTUsIG91dC53aWR0aD02LCBmaWcucmV0aW5hPTJ9CiMgZmlnLndpZHRoID0gMywgZmlnLmhlaWdodCA9IDUsIG91dC5oZWlnaHQ9Mi41LCBvdXQud2lkdGg9MywgZmlnLnJldGluYSA9MyBmb3IgbWFjYm9vayBzY3JlZW4KIyBkb3VibGUgdGhhdCBmb3IgZXh0ZXJuYWwgbW9uaXRvcgpjb2VmcyA8LSBhcy5kYXRhLnRhYmxlKHN1bW1hcnkobW9kVGZ1bGwxKSR0VGFibGUpCmNvZWZzMiA8LSBhcy5kYXRhLnRhYmxlKHN1bW1hcnkobW9kVGZ1bGxKYmV0YSkkdFRhYmxlKQpjb2VmczMgPC0gYXMuZGF0YS50YWJsZShzdW1tYXJ5KG1vZFRmdWxsSG9ybikkdFRhYmxlKQoKY29lZnMkbW9kIDwtICdKdHUnCmNvZWZzMiRtb2QgPC0gJ0piZXRhJwpjb2VmczMkbW9kIDwtICdIb3JuJwoKY29lZnMkdmFyIDwtIHJvd25hbWVzKHN1bW1hcnkobW9kVGZ1bGwxKSR0VGFibGUpCmNvZWZzMiR2YXIgPC0gcm93bmFtZXMoc3VtbWFyeShtb2RUZnVsbEpiZXRhKSR0VGFibGUpCmNvZWZzMyR2YXIgPC0gcm93bmFtZXMoc3VtbWFyeShtb2RUZnVsbEhvcm4pJHRUYWJsZSkKCiMgZXh0cmFjdCB0ZW1wZXJhdHVyZSBlZmZlY3RzIGFuZCBiaW5kIG1vZGVsIGNvZWZzIHRvZ2V0aGVyCmNvbHMgPC0gYygndmFyJywgJ1ZhbHVlJywgJ1N0ZC5FcnJvcicsICdtb2QnKQoKYWxsY29lZnNmdWxsIDwtIHJiaW5kKGNvZWZzW2dyZXAoJ3RlbXB0cmVuZHxSRUFMTScsIHZhciksIC4uY29sc10sIAogICAgICAgICAgICAgICAgICAgICAgY29lZnMyW2dyZXAoJ3RlbXB0cmVuZHxSRUFMTScsIHZhciksIC4uY29sc10sIAogICAgICAgICAgICAgICAgICAgICAgY29lZnMzW2dyZXAoJ3RlbXB0cmVuZHxSRUFMTScsIHZhciksIC4uY29sc10pCmFsbGNvZWZzZnVsbCR2YXJbYWxsY29lZnNmdWxsJHZhciA9PSAndGVtcHRyZW5kX2Ficy5zYyddIDwtICd0ZW1wdHJlbmRfYWJzLnNjOlJFQUxNRnJlc2h3YXRlcicKCiMgYWRkIGF2ZXJhZ2UgdGVtcGVyYXR1cmUgZWZmZWN0IChhY3Jvc3MgcmVhbG1zKSB0byByZWFsbS1zcGVjaWZpYyB0ZW1wZXJhdHVyZSBlZmZlY3RzCm1lYW50ZW1wZWZmZWN0IDwtIGFsbGNvZWZzZnVsbFt2YXIgPT0gJ3RlbXB0cmVuZF9hYnMuc2M6UkVBTE1GcmVzaHdhdGVyJywgbWVhbihWYWx1ZSksIGJ5ID0gbW9kXSRWMQphbGxjb2Vmc2Z1bGxbdmFyID09ICd0ZW1wdHJlbmRfYWJzLnNjOlJFQUxNTWFyaW5lJywgVmFsdWUgOj0gVmFsdWUgKyBtZWFudGVtcGVmZmVjdF0KYWxsY29lZnNmdWxsW3ZhciA9PSAndGVtcHRyZW5kX2Ficy5zYzpSRUFMTVRlcnJlc3RyaWFsJywgVmFsdWUgOj0gVmFsdWUgKyBtZWFudGVtcGVmZmVjdF0KCiMgYWRkIGJhc2UgdGVtcGVyYXR1cmU6aHVtYW4gZWZmZWN0IChmcmVzaHdhdGVyKSB0byByZWFsbS1zcGVjaWZpYyB0ZW1wZXJhdHVyZTpodW1hbiBlZmZlY3RzCmFsbGNvZWZzZnVsbCRWYWx1ZVthbGxjb2Vmc2Z1bGwkdmFyID09ICd0ZW1wdHJlbmRfYWJzLnNjOlJFQUxNTWFyaW5lOmh1bWFuLnNjJ10gPC0gd2l0aChhbGxjb2Vmc2Z1bGwsIFZhbHVlW3ZhciA9PSAndGVtcHRyZW5kX2Ficy5zYzpSRUFMTU1hcmluZTpodW1hbi5zYyddICsgVmFsdWVbdmFyID09ICd0ZW1wdHJlbmRfYWJzLnNjOmh1bWFuLnNjJ10pCmFsbGNvZWZzZnVsbCRWYWx1ZVthbGxjb2Vmc2Z1bGwkdmFyID09ICd0ZW1wdHJlbmRfYWJzLnNjOlJFQUxNVGVycmVzdHJpYWw6aHVtYW4uc2MnXSA8LSB3aXRoKGFsbGNvZWZzZnVsbCwgVmFsdWVbdmFyID09ICd0ZW1wdHJlbmRfYWJzLnNjOlJFQUxNVGVycmVzdHJpYWw6aHVtYW4uc2MnXSArIFZhbHVlW3ZhciA9PSAndGVtcHRyZW5kX2Ficy5zYzpodW1hbi5zYyddKQoKCiMgcmVtb3ZlIG5vbi10ZW1wZXJhdHVyZSBlZmZlY3RzCmFsbGNvZWZzZnVsbCA8LSBhbGxjb2Vmc2Z1bGxbZ3JlcGwoJzonLCBhbGxjb2Vmc2Z1bGwkdmFyKSAmIGdyZXBsKCd0ZW1wdHJlbmQnLCBhbGxjb2Vmc2Z1bGwkdmFyKSwgXQoKIyBhZGQgaW5mbyBmb3IgcGxvdHRpbmcKYWxsY29lZnNmdWxsJGxDSSA8LSBhbGxjb2Vmc2Z1bGwkVmFsdWUgLSBhbGxjb2Vmc2Z1bGwkU3RkLkVycm9yICMgbG93ZXIgY29uZmlkZW5jZSBpbnRlcnZhbAphbGxjb2Vmc2Z1bGwkdUNJIDwtIGFsbGNvZWZzZnVsbCRWYWx1ZSArIGFsbGNvZWZzZnVsbCRTdGQuRXJyb3IKbnZhciA8LSBucm93KGFsbGNvZWZzZnVsbCkvMwphbGxjb2Vmc2Z1bGwkeSA8LSAxOm52YXIgKyByZXAoYygwLCAwLjEsIDAuMiksIGMobnZhciwgbnZhciwgbnZhcikpICMgeS12YWx1ZXMKCmFsbGNvZWZzZnVsbCR2YXJuYW1lIDwtIGdzdWIoJ3RlbXB0cmVuZF9hYnMuc2M6fHRlbXB0cmVuZC5zYzonLCAnJywgYWxsY29lZnNmdWxsJHZhcikKYWxsY29lZnNmdWxsJHZhcm5hbWUgPC0gZ3N1YignUkVBTE0nLCAnJywgYWxsY29lZnNmdWxsJHZhcm5hbWUpCmFsbGNvZWZzZnVsbCR2YXJuYW1lIDwtIGdzdWIoJy5zYycsICcnLCBhbGxjb2Vmc2Z1bGwkdmFybmFtZSkKYWxsY29lZnNmdWxsJHZhcm5hbWUgPC0gZ3N1YignXmh1bWFuJCcsICdGcmVzaHdhdGVyOmh1bWFuJywgYWxsY29lZnNmdWxsJHZhcm5hbWUpCgp4bGltczEgPC0gYygwLjAsIDAuMDUpICMgZm9yIHJlYWxtcwp4bGltczIgPC0gYygtMC4wMSwgMC4wMTUpICMgZm9yIHRyYWl0cwp4bGltczMgPC0gYygtMC4wMDQsIDAuMDAyNSkgIyBmb3IgZW52aXJvbm1lbnQKeGxpbXM0IDwtIGMoLTAuMDE2LCAwLjAwNSkgIyBmb3IgY29tbXVuaXR5CnhsaW1zNSA8LSBjKC0wLjAxLCAwLjAxNSkgIyBmb3IgaHVtYW4KCmRkZyA8LSAwLjUgIyBkb2RnZSBmb3IgZWFjaCBtb2RlbAoKc2V0MSA8LSBjKCdUZXJyZXN0cmlhbCcsICdNYXJpbmUnLCAnRnJlc2h3YXRlcicpCnNldDIgPC0gYygnbWFzcycsICdzcGVlZCcsICdsaWZlc3BhbicsICdjb25zdW1lcmZyYWMnLCAnZW5kb3RoZXJtZnJhYycsICd0ZW1wYXZlX21ldGFiJykKc2V0MyA8LSBjKCdzZWFzJywgJ21pY3JvY2xpbScsICd0ZW1wYXZlJykKc2V0NCA8LSBjKCducHAnLCAnbnNwcCcsICd0aGVybWFsX2JpYXMnKQpzZXQ1IDwtIGMoJ1RlcnJlc3RyaWFsOmh1bWFuJywgJ01hcmluZTpodW1hbicsICdGcmVzaHdhdGVyOmh1bWFuJykKCnAxIDwtIGdncGxvdChzdWJzZXQoYWxsY29lZnNmdWxsLCB2YXJuYW1lICVpbiUgc2V0MSksIAogICAgICAgICAgICAgICAgICAgIGFlcyh2YXJuYW1lLCBWYWx1ZSwgZ3JvdXAgPSBtb2QsIGNvbG9yID0gbW9kKSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGxpbmV0eXBlID0gJ2Rhc2hlZCcsIGNvbG9yID0gJ2xpZ2h0IGdyZXknKSArCiAgZ2VvbV9lcnJvcmJhcihhZXMoeW1pbiA9IGxDSSwgeW1heCA9IHVDSSksIHdpZHRoID0gMCwgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZShkZGcpKSArIAogIGdlb21fcG9pbnQocG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZShkZGcpKSArIAogIGxhYnMoeSA9ICdUZW1wZXJhdHVyZSBjaGFuZ2UgZWZmZWN0JywgeCA9ICcnLCB0YWcgPSAnQScpICsKICBzY2FsZV9jb2xvcl9ncmV5KCkgKyAKICB0aGVtZShwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9ibGFuaygpLCBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksIGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiYmxhY2siKSwKICAgICAgICBsZWdlbmQucG9zaXRpb249J25vbmUnLAogICAgICAgIGF4aXMudGV4dD1lbGVtZW50X3RleHQoc2l6ZT03KSwKICAgICAgICBheGlzLnRpdGxlPWVsZW1lbnRfdGV4dChzaXplPTcpKSArIAogIGNvb3JkX2ZsaXAoeWxpbSA9IHhsaW1zMSkKCnAyIDwtIGdncGxvdChzdWJzZXQoYWxsY29lZnNmdWxsLCB2YXJuYW1lICVpbiUgc2V0MiksIAogICAgICAgICAgICAgICAgICAgIGFlcyh2YXJuYW1lLCBWYWx1ZSwgZ3JvdXAgPSBtb2QsIGNvbG9yID0gbW9kKSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGxpbmV0eXBlID0gJ2Rhc2hlZCcsIGNvbG9yID0gJ2xpZ2h0IGdyZXknKSArCiAgZ2VvbV9lcnJvcmJhcihhZXMoeW1pbiA9IGxDSSwgeW1heCA9IHVDSSksIHdpZHRoID0gMCwgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZShkZGcpKSArIAogIGdlb21fcG9pbnQocG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZShkZGcpKSArIAogIGxhYnMoeSA9ICdJbnRlcmFjdGlvbiB3aXRoIHRlbXBlcmF0dXJlIGNoYW5nZSBlZmZlY3QnLCB4ID0gJycsIHRhZyA9ICdCJykgKwogIHNjYWxlX2NvbG9yX2dyZXkoKSArIAogIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2JsYW5rKCksIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwgYXhpcy5saW5lID0gZWxlbWVudF9saW5lKGNvbG91ciA9ICJibGFjayIpLAogICAgICAgIGxlZ2VuZC5wb3NpdGlvbj0nbm9uZScsCiAgICAgICAgYXhpcy50ZXh0PWVsZW1lbnRfdGV4dChzaXplPTcpLAogICAgICAgIGF4aXMudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9NykpICsgCiAgY29vcmRfZmxpcCh5bGltID0geGxpbXMyKQoKcDMgPC0gZ2dwbG90KHN1YnNldChhbGxjb2Vmc2Z1bGwsIHZhcm5hbWUgJWluJSBzZXQzKSwgCiAgICAgICAgICAgICAgICAgICAgYWVzKHZhcm5hbWUsIFZhbHVlLCBncm91cCA9IG1vZCwgY29sb3IgPSBtb2QpKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgbGluZXR5cGUgPSAnZGFzaGVkJywgY29sb3IgPSAnbGlnaHQgZ3JleScpICsKICBnZW9tX2Vycm9yYmFyKGFlcyh5bWluID0gbENJLCB5bWF4ID0gdUNJKSwgd2lkdGggPSAwLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKGRkZykpICsgCiAgZ2VvbV9wb2ludChwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKGRkZykpICsgCiAgbGFicyh5ID0gJ0ludGVyYWN0aW9uIHdpdGggdGVtcGVyYXR1cmUgY2hhbmdlIGVmZmVjdCcsIHggPSAnJywgdGFnID0gJ0MnKSArCiAgc2NhbGVfY29sb3JfZ3JleSgpICsgCiAgdGhlbWUocGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfYmxhbmsoKSwgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLCBheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gImJsYWNrIiksCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uPSdub25lJywKICAgICAgICBheGlzLnRleHQ9ZWxlbWVudF90ZXh0KHNpemU9NyksCiAgICAgICAgYXhpcy50aXRsZT1lbGVtZW50X3RleHQoc2l6ZT03KSkgKyAKICBjb29yZF9mbGlwKHlsaW0gPSB4bGltczMpCgpwNCA8LSBnZ3Bsb3Qoc3Vic2V0KGFsbGNvZWZzZnVsbCwgdmFybmFtZSAlaW4lIHNldDQpLCAKICAgICAgICAgICAgICAgICAgICBhZXModmFybmFtZSwgVmFsdWUsIGdyb3VwID0gbW9kLCBjb2xvciA9IG1vZCkpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSA9ICdkYXNoZWQnLCBjb2xvciA9ICdsaWdodCBncmV5JykgKwogIGdlb21fZXJyb3JiYXIoYWVzKHltaW4gPSBsQ0ksIHltYXggPSB1Q0kpLCB3aWR0aCA9IDAsIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2UoZGRnKSkgKyAKICBnZW9tX3BvaW50KHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2UoZGRnKSkgKyAKICBsYWJzKHkgPSAnSW50ZXJhY3Rpb24gd2l0aCB0ZW1wZXJhdHVyZSBjaGFuZ2UgZWZmZWN0JywgeCA9ICcnLCB0YWcgPSAnRCcpICsKICBzY2FsZV9jb2xvcl9ncmV5KCkgKyAKICB0aGVtZShwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9ibGFuaygpLCBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksIGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiYmxhY2siKSwKICAgICAgICBsZWdlbmQucG9zaXRpb249J25vbmUnLAogICAgICAgIGF4aXMudGV4dD1lbGVtZW50X3RleHQoc2l6ZT03KSwKICAgICAgICBheGlzLnRpdGxlPWVsZW1lbnRfdGV4dChzaXplPTcpKSArIAogIGNvb3JkX2ZsaXAoeWxpbSA9IHhsaW1zNCkKCnA1IDwtIGdncGxvdChzdWJzZXQoYWxsY29lZnNmdWxsLCB2YXJuYW1lICVpbiUgc2V0NSksIAogICAgICAgICAgICAgICAgICAgIGFlcyh2YXJuYW1lLCBWYWx1ZSwgZ3JvdXAgPSBtb2QsIGNvbG9yID0gbW9kKSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGxpbmV0eXBlID0gJ2Rhc2hlZCcsIGNvbG9yID0gJ2xpZ2h0IGdyZXknKSArCiAgZ2VvbV9lcnJvcmJhcihhZXMoeW1pbiA9IGxDSSwgeW1heCA9IHVDSSksIHdpZHRoID0gMCwgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZShkZGcpKSArIAogIGdlb21fcG9pbnQocG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZShkZGcpKSArIAogIGxhYnMoeSA9ICdJbnRlcmFjdGlvbiB3aXRoIHRlbXBlcmF0dXJlIGNoYW5nZSBlZmZlY3QnLCB4ID0gJycsIHRhZyA9ICdFJykgKwogIHNjYWxlX2NvbG9yX2dyZXkoKSArIAogIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2JsYW5rKCksIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwgYXhpcy5saW5lID0gZWxlbWVudF9saW5lKGNvbG91ciA9ICJibGFjayIpLAogICAgICAgIGxlZ2VuZC5wb3NpdGlvbj0nbm9uZScsCiAgICAgICAgYXhpcy50ZXh0PWVsZW1lbnRfdGV4dChzaXplPTcpLAogICAgICAgIGF4aXMudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9NykpICsgCiAgY29vcmRfZmxpcCh5bGltID0geGxpbXM1KQoKZ3JpZC5hcnJhbmdlKHAxLCBwMiwgcDMsIHA0LCBwNSwgbmNvbCA9IDIsIGxheW91dF9tYXRyaXggPSByYmluZChjKDEsMiksIGMoMyw0KSwgYyg1LCBOQSkpKQoKCmBgYAoKIyBUbyBkbwoK